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}`,
}
];
Please see my article