首先,我的问题的一些背景信息:我有一个项目,在其中我通过 Socket.IO 接收一个对象,因此我没有关于它的类型信息。此外,它是一种相当复杂的类型,因此需要进行大量检查以确保接收到的数据良好。
问题是我需要访问由接收到的对象中的字符串指定的本地对象的属性。这对于第一个维度来说效果很好,因为我可以将任何类型的属性说明符转换为keyof typeof
无论我想访问什么(例如this.property[<keyof typeof this.property> data.property]
).
结果变量的类型显然是一个相当冗长的联合类型(联合所有属性的所有类型)this.property
有)。一旦这些属性之一属于非原始类型keyof typeof subproperty
被推断为never
.
通过之前所做的检查,我可以保证该属性存在,并且我 99% 确信代码一旦编译就会运行。只是编译器在抱怨。
下面是一些非常简单的代码,可以重现此行为以及观察到的和预期的类型。
const str = 'hi';
const obj = {};
const complexObj = {
name: 'complexObject',
innerObj: {
name: 'InnerObject',
},
};
let strUnion: typeof str | string; // type: string
let objUnion: typeof obj | string; // type: string | {}
let complexUnion: typeof complexObj | string; // type: string | { ... as expected ... }
let strTyped: keyof typeof str; // type: number | "toString" | "charAt" | ...
let objTyped: keyof typeof obj; // type: never (which makes sense as there are no keys)
let complexObjTyped: keyof typeof complexObj; // type: "name" | "innerObject"
let strUnionTyped: keyof typeof strUnion; // type: number | "toString" | ...
let objUnionTyped: keyof typeof objUnion; // type: never (expected: number | "toString" | ... (same as string))
let complexUnionTyped: keyof typeof complexUnion; // type: never (expected: "name" | "innerObject" | number | "toString" | ... and all the rest of the string properties ...)
let manuallyComplexUnionTyped: keyof string | { name: string, innerObj: { name: string }}; // type: number | "toString" | ... (works as expected)
这是 TypeScript(版本 3)的已知限制还是我在这里遗漏了一些东西?
如果您有联合,则只能访问公共属性。keyof
将为您提供某种类型的可公开访问的密钥。
For strUnionTyped
之间的并集string
和字符串文字类型'hi'
结果类型将具有与 string 相同的属性,因为联合中的两种类型具有与 string 相同的键。
For objUnionTyped
and complexUnionTyped
联合体没有公共键,因此结果将是never
For manuallyComplexUnionTyped
你得到的钥匙string
,因为你写的实际上是(keyof string) | { name: string, innerObj: { name: string }}
not keyof (string | { name: string, innerObj: { name: string }})
所以你得到了钥匙string
在与您指定的对象类型的联合中。
要获取联合体所有成员的键,您可以使用条件类型:
type AllUnionMemberKeys<T> = T extends any ? keyof T : never;
let objUnionTyped: AllUnionMemberKeys<typeof objUnion>;
let complexUnionTyped: AllUnionMemberKeys<typeof complexUnion>;
Edit
条件类型有助于获取所有联合成员的键的原因是因为条件类型分发超过裸类型参数。所以在我们的例子中
AllUnionMemberKeys<typeof objUnion> = (keyof typeof obj) | (keyof string)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)