1

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?

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.