首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型记录:宾语和原语之间的合并类型的键永远不会。

问类型记录:宾语和原语之间的合并类型的键永远不会。
EN

Stack Overflow用户
提问于 2018-09-07 11:24:58
回答 1查看 5.1K关注 0票数 5

首先,我的问题有一点上下文:我有一个通过Socket.IO接收对象的项目,因此我没有关于它的类型信息。另外,它是一个相当复杂的类型,因此需要进行大量的检查,以确保接收到的数据是好的。

问题是,我需要访问由接收对象中的字符串指定的本地对象的属性。对于第一个维度,这是可以的,因为我可以将任意类型的属性说明符强制转换为keyof typeof,不管它是什么,我想访问什么(例如,this.property[<keyof typeof this.property> data.property])。

结果变量的类型显然是一个相当长的联合类型(将this.property拥有的所有属性的所有类型合并在一起)。一旦这些属性之一是非原语类型,keyof typeof subproperty就被推断为never。

通过前面所做的检查,我可以保证该属性的存在,并且我99%确信代码将在编译后运行。只是编译器在抱怨。

下面是一些非常简单的代码,可以复制这种行为以及观察到的和预期的类型。

代码语言:javascript
复制
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版)的限制,还是我在这里遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-07 11:33:36

如果您有一个联合,则只有公共属性是可访问的。keyof将为您提供可公开访问的类型密钥。

对于strUnionTyped ( string和字符串文本类型'hi'之间的一个联合),生成的类型将具有与string相同的属性,与联合中的两个类型具有与string相同的键。

对于objUnionTyped和complexUnionTyped,联合没有公共密钥,因此结果将是never

对于manuallyComplexUnionTyped,您可以得到string的键,因为您编写的实际上是(keyof string) | { name: string, innerObj: { name: string }}而不是keyof (string | { name: string, innerObj: { name: string }}),所以您可以在与指定的对象类型结合的情况下获得string的键。

要获取联合的所有成员的键,可以使用条件类型:

代码语言:javascript
复制
type AllUnionMemberKeys<T> = T extends any ? keyof T : never;
let objUnionTyped: AllUnionMemberKeys<typeof objUnion>;
let complexUnionTyped: AllUnionMemberKeys<typeof complexUnion>;

编辑

条件类型帮助获取所有联合成员的键的原因是条件类型分送优于裸类型参数。所以在我们的情况下

代码语言:javascript
复制
AllUnionMemberKeys<typeof objUnion> = (keyof typeof obj) | (keyof string)
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52221574

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档