我正在尝试创建语言环境字符串对象:
const strings = {
hello: {
en: 'hello',
pl: 'hej'
},
bye: {
en: 'bye',
pl: 'pa'
}
}
如果我输入strings.
并向我显示hello
和bye
可用,则此方法有效。但是,这并没有强制执行任何操作,某些属性可能会丢失en
或pl
或什至没有其他属性。为了更具体,我声明了一个枚举并键入了对象:
enum Language {
en = 'en',
pl = 'pl'
}
type Strings = { [k: string]: { [lang in Language]: string } }
const strings: Strings = {
// ...same as before
}
太好了!现在,我的strings
属性已正确键入。但是,等等,现在由于[k: string]
,我失去了在属性上的键入。根据ts,strings.dontExist
现在可以了(可以理解)。
所以我的问题是我如何实现推断的属性(就像第一个示例中一样),但又要获得我明确设置的强类型属性({ [lang in Language]: string }
)?
[使用打字稿3.6.2]
答案 0 :(得分:1)
虽然我认为如果您改变结构(例如将en
和pl
放在顶层,则输入起来会容易得多),但我认为您必须创建对象,然后将键的类型推断为新对象,如下所示:
enum Language {
en = 'en',
pl = 'pl'
}
type Translation = { [lang in Language]: string }
const strings = {
hello: {
en: 'hello',
pl: 'hej'
},
bye: {
en: 'bye',
pl: 'pa'
}
}
type TranslationGroup = keyof typeof strings;
const typed: Record<TranslationGroup, Translation> = strings
typed.foo //error
答案 1 :(得分:1)
我可能只是将Strings
的键K
设为通用,像这样:
type Strings<K extends string> = { [P in K]: { [L in Language]: string } };
然后,您可以使用一个小的辅助函数从对象文字中推断出K
,而不必强迫您重新输入它:
const asStrings = <K extends string>(s: Strings<K>) => s;
它是这样的:
const strings = asStrings({
hello: {
en: "hello",
pl: "hej"
},
bye: {
en: "bye",
pl: "pa"
}
}); // Strings<"hello" | "bye">
如果您省略一种语言,则应该会出错。希望有帮助!