Параметр типа реализации интерфейса извлечения

#typescript #typescript-generics

Вопрос:

Я пытаюсь извлечь параметр типа интерфейса, чтобы использовать его в качестве параметра для универсальной функции.

На практике у меня есть эти общие типы

 interface ITranslatablelt;T, K extends keyof Tgt; {  translations: ITranslationlt;T, Kgt; }  export type ITranslationlt;T, K extends keyof Tgt; =  {  lang: string  } amp; {  [P in K]?: T[P];  };  

Я хочу использовать эти типы следующим образом

 interface MyType extends ITranslatablelt;MyType, "name" | "description"gt; {  id: string;  name: string;  description: string; }  

функция, которую я использую для этого :

 export type TranslationKeyslt;Tgt; = T extends ITranslatablelt;T, infer Kgt;  ? K  : never;  export function translatelt;T extends ITranslatablelt;T, TranslationKeyslt;Tgt;gt;gt;(item: T, key: TranslationKeyslt;Tgt;, language: string = DEFAULT_LANGUAGE) {  return language === DEFAULT_LANGUAGE  ? item[key]  : item.translations?.find(translation =gt; translation.lang === language)?.[key] ?? item[key]; }  

и я использую его вот так translate(myItem, 'name', 'en'); , например.

Все это, кажется, компилируется правильно, но каждый раз, когда я использую свою translate функцию, автозаполнение для второго аргумента дает мне полный список T ключей. Я хотел бы правильно ввести свою функцию, чтобы автозаполнение давало мне только ключи, которые я передал в качестве второго параметра, когда я его расширяю.

Например, для :

 interface Foo extends ITranslatablelt;Foo, 'name' | 'description'gt; {  id: string;  name: string;  description: string; }  

это дает мне 'id' | 'name' | 'description' | 'translations' , и я бы хотел, чтобы это дало мне 'name' | 'description' вместо.

Есть какие-нибудь идеи ?

Ответ №1:

Я нашел решение. Я не изменил свои интерфейсы, но изменил свою функцию на :

 type Unwrappedlt;Tgt; = T extends (infer U)[]  ? U  : T;  export function translatelt;T extends ITranslatablelt;T, Kgt;, K extends keyof Tgt;(  item: T,  key: Excludelt;keyof Unwrappedlt;T['translations']gt;, 'lang'gt;,  language: string = DEFAULT_LANGUAGE ): string {  return (  language === DEFAULT_LANGUAGE  ? item[key as keyof T]  : (item.translations  ?.find(translation =gt; translation.lang === language)  ?.[key as keyof ITranslationlt;T, Kgt;]  ?? item[key as keyof T])  ) as string; }