示例代码:
enum ENUM_A {
ONE="ONE",
TWO="TWO",
THREE="THREE",
FOUR="FOUR"
}
interface TYPE_A {
myArray: ENUM_A[],
mySpecificMapping: {
[key in ENUM_A]?: boolean
}
}
const myObject: TYPE_A = {
myArray: [ENUM_A.ONE, ENUM_A.THREE],
mySpecificMapping: {
[ENUM_A.ONE]: true,
// Uncommenting the line below should result in a TypeScript error
// [ENUM_A.TWO]: true,
[ENUM_A.THREE]: true,
// Uncommenting the line below should result in a TypeScript error
// [ENUM_A.FOUR]: true,
}
}
如果“mySpecificMapping”包含“myArray”中不存在的键,则 myObject 应该出错
我想我需要在这里使用自引用类型?
是的,要实现此功能,您需要
TypeA
在 EnumA
中实际存在的 myArray
成员中成为 generic,如下所示:
interface TypeA<T extends EnumA> {
myArray: T[],
mySpecificMapping: {
[K in T]?: boolean
}
}
然后您可以将注释更改为
const myObject: TypeA<EnumA.ONE | EnumA.THREE> = {
myArray: [EnumA.ONE, EnumA.THREE],
mySpecificMapping: {
[EnumA.ONE]: true,
[EnumA.THREE]: true
}
}
如果您将
[EnumA.TWO]: true
添加到 mySpecificMapping
,则会出现错误。但写出 EnumA.ONE | EnumA.THREE
类型的参数是乏味且多余的。如果 TypeScript 能够为您推断该类型参数,那就太好了,但这是 microsoft/TypeScript#32794 所请求的缺失功能。
如果你想要泛型类型参数推断,你需要创建一个泛型function来配合
TypeA
。这是一个用于此目的的辅助函数:
const typeA = <T extends EnumA>(t: TypeA<T>) => t;
const myObject = typeA({
myArray: [EnumA.ONE, EnumA.THREE],
mySpecificMapping: {
[EnumA.ONE]: true,
[EnumA.THREE]: true,
}
});
现在您将看到
myObject
被推断为类型 TypeA<EnumA.ONE | EnumA.THREE>
,而无需您自己写出来。写 const myObject = typeA({⋯})
而不是 const myObject: TypeA = {⋯}
的工作量和击键次数大约相同,所以希望这是可以接受的。
无论如何,让我们确保您得到您所要求的行为:
const myObject = typeA({
myArray: [EnumA.ONE, EnumA.THREE],
mySpecificMapping: {
[EnumA.ONE]: true,
[EnumA.TWO]: true, // error!
[EnumA.THREE]: true,
}
});
看起来不错。当您添加
mySpecificMapping
中不存在的 myArray
键时,您会收到错误消息。