假设我有一个Resource
接口,它有大约translations
个.
这是我翻译的模型的"记录库".
我对"真实"记录也有类似的界面,比如产品:
interface Translation {
locale: string
}
interface Resource<T extends Translation> {
translations: T[]
}
interface ProductTranslation {
locale: string,
title: string,
status: number
}
interface Product {
translations: ProductTranslation[]
}
我想编写一个"生成器"函数,该函数将为给定的翻译属性返回一个getter,例如,在Vanilla JS中:
function getTranslationValue(locale, key) {
return (resource) => {
const translation = resource.translations.find(t => t.locale === locale)
return (translation && translation[key]) || null
}
}
我发现在TS中编写它的唯一方法需要声明2个泛型类型:
- 资源类型(
R<T>
) - 资源转换类型(
T extends Translation
)
就像这样:
function getTranslationValue<R extends Resource<T>, T extends Translation>(
locale: R['translations'][number]['locale'],
key: keyof R['translations'][number]
) {
return (resource: R) => {
const translation = resource.translations.find(t => t.locale === locale)
const value = translation && translation[key]
return value ?? null
}
}
然后,我可以这样使用它:
const getTitle = generateGetTranslationValue<Product, Product['translations'][number]>('en', 'title')
getTitle(myProduct)
有没有一种方法可以go 掉Product['translations'][number]
声明,让调用看起来像这样:
const getTitle = generateGetTranslationValue<Product>('en', 'title')
getTitle(myProduct)