#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; }