【发布时间】:2021-12-08 12:42:32
【问题描述】:
我想强烈键入指向特定类型的点分隔路径。假设我们有一个递归结构,其中每个叶子都是一个特定的类型,在这种情况下由一组语言翻译:
type Language = "pl" | "en";
type Translation = { [ lang in Language ]: string };
type Translations = { [key: string]: Translation | Translations | undefined };
这方面的一个例子可能是:
const translations = {
hello: {
pl: "Dzieńdobry",
en: "Hello",
},
bool: {
yes: {
pl: "Tak",
en: "Yes",
},
no: {
pl: "Nie",
en: "No",
},
},
};
我想要路径类型:"hello"、"bool.yes" 和 "bool.no",但 不是 到 "bool" 或 "missing" 或 "bool.foo" or "hello.pl"` .到目前为止,这是我所拥有的:
对于单层翻译文件:
type KeyToTranslation<T extends Translations, K extends string = string> = K extends keyof T
? T[K] extends Translation
? K
: never
: never;
function printTranslationByKey<T extends Translations, K extends string>(
t: T,
k: KeyToTranslation<T, K>
) {
console.log(t[k]);
}
printTranslationByKey(translations, "hello"); // Valid, Correct!
printTranslationByKey(translations, "hello.pl"); // Error, Correct!
printTranslationByKey(translations, "missing"); // Error, Correct!
printTranslationByKey(translations, "bool.yes"); // Error, Incorrect.
所以我们需要一些模板字符串和infers。不幸的是,我似乎无法让这个工作。似乎忘记了我已经断言T[TKey] extends Translations:
type DeepKeyToTranslation<T extends Translations, K extends string = string> = K extends keyof T
? T[K] extends Translation
? K
: never
:
// This is where we extend this further to cover the dot separated case:
K extends `${infer TKey}.${infer Rest}`
? TKey extends keyof T
? T[TKey] extends undefined
? never
: T[TKey] extends Translations
? Rest extends DeepKeyToTranslation<T[TKey], Rest>
? K
: never
: never
: never
: never;
function printTranslationByDeepKey<T extends Translations, K extends string>(
t: T,
k: DeepKeyToTranslation<T, K>
) {
console.log(t[k]);
}
printTranslationByDeepKey(translations, "hello"); // Good!
printTranslationByDeepKey(translations, "hello.pl"); // Error
printTranslationByDeepKey(translations, "missing"); // Error
失败是因为:
Type 'T[TKey]' does not satisfy the constraint 'Translations'.
Type 'T[string]' is not assignable to type 'Translations'.
Type 'Translation | Translations | undefined' is not assignable to type 'Translations'.
Type 'undefined' is not assignable to type 'Translations'.()
我发现了其他几个类似的问题:
第二个甚至是我当前实现的基础,但两者都没有提供类似的功能,您可以根据路径中的值的类型停止递归。
【问题讨论】:
标签: typescript