I am attempting to extract a type parameter from an interface in order to use it as a parameter for a generic function.
In my particular scenario, I have the following generic types:
interface ITranslatable<T, K extends keyof T> {
translations: ITranslation<T, K>
}
export type ITranslation<T, K extends keyof T> =
{
lang: string
} & {
[P in K]?: T[P];
};
I aim to employ these types in the following manner:
interface MyType extends ITranslatable<MyType, "name" | "description"> {
id: string;
name: string;
description: string;
}
The generic function I utilize is defined as follows:
export type TranslationKeys<T> = T extends ITranslatable<T, infer K>
? K
: never;
export function translate<T extends ITranslatable<T, TranslationKeys<T>>>(item: T, key: TranslationKeys<T>, language: string = DEFAULT_LANGUAGE) {
return language === DEFAULT_LANGUAGE
? item[key]
: item.translations?.find(translation => translation.lang === language)?.[key] ?? item[key];
}
To call this function, I use translate(myItem, 'name', 'en');
, for example.
While everything appears to compile correctly, each time I invoke my translate
function,
the autocompletion for the second argument provides me with the entire list of keys present in T
.
I desire to properly type my function so that the autocompletion only displays the
keys I provided as the second parameter when extending it.
For instance, when using:
interface Foo extends ITranslatable<Foo, 'name' | 'description'> {
id: string;
name: string;
description: string;
}
it currently shows
'id' | 'name' | 'description' | 'translations'
, whereas I would prefer it to display
'name' | 'description'
exclusively.
Any suggestions?