Home > front end >  Typescript: interface with generics - applying inside defined object
Typescript: interface with generics - applying inside defined object

Time:09-17

I have an interface with generics:

interface InterfaceWithGenerics<
  Dict extends Record<string, any>,
  Key extends keyof Dict = keyof Dict
> {
  key: Key;
  dictValueFormatter: ((key: Key, value: Dict[Key]) => any);
}

When I define object, which implements this interface, I expect generics to be applied to object properties and instantiate their types. For example:

interface SomeDictionary {
  foo: string;
  bar: number;
  baz: boolean;
}

export const dictConfig: InterfaceWithGenerics<SomeDictionary>[] = [
  {
    key: 'foo',
    dictValueFormatter: (key, value) => `${key}:${value}`,
  }
];

But it not happens. VS Code shows the following typing for dictValueFormatter inside object with prop key='foo' (Fact):

(key: keyof SomeDictionary, value: string | number | boolean) => any

Expected:

(key: 'foo', value: string) => any

Question: How to declare an interface with generics that will more specifically instantiate the types of properties in specific situations?

CodePudding user response:

You need to define discriminated union:

type InterfaceWithGenerics<
  Dict extends Record<string, any>,
  > = {
    [Key in keyof Dict]: {
      key: Key;
      dictValueFormatter: ((key: Key, value: Dict[Key]) => any);
    }
  }

type Values<T> = T[keyof T]


interface SomeDictionary {
  foo: string;
  bar: number;
  baz: boolean;
}

export const dictConfig: Values<InterfaceWithGenerics<SomeDictionary>>[] = [
  {
    key: 'foo',
    dictValueFormatter: (key, value) => `${key}:${value}`,
  }
];

Playground

Please see my article

  • Related