Search code examples
javascripttypescriptgenericsmapped-types

Resolve Generic of Generic


I'm trying to create a reusable utility type in TypeScript that works with any map type conforming to a generic structure. Here's my basic setup:

type SomeMap<T> = {
  [key: string]: T;
};

I need to define a Resolve type that can dynamically work with any map type extending SomeMap. Here's my attempt that results in errors:

type Resolve<T, K extends keyof Map, Map extends SomeMap<T>> = {
  result: Map<T>[K]; // Syntax error: can only be: Map[K]
};

This fails because TypeScript doesn't support this form of generics nesting or constraint directly. I'm looking for a way to make Resolve work with any type that matches SomeMap without hardcoding the map type into the Resolve definition.

Clearly, it's possible to hardcode the map in the following way:

type ResolveWorks<T, K extends keyof SomeMap<T>> = {
  result: SomeMap<T>[K];
};

However, this approach does not meet my requirements because it lacks reusability—I need a solution that is adaptable to different map structures without specifying SomeMap directly.


Solution

  • Workaround:

    type IsString<T> = T extends string ? true : false;
    
    type IsNumber<T> = T extends number ? true : false;
    
    type Resolve<T, HS, HN> = IsString<T> extends true
      ? HS
      : IsNumber<T> extends true
      ? HN
      : never;
    
    type HandleString<T> = {
      type: 'string';
      v: T;
    };
    
    type HandleNumber<T> = {
      type: 'number';
      v: T;
    };
    
    type Result<T> = Resolve<string, HandleString<T>, HandleNumber<T>>;