在 Typescript 中,当传播 类型的变量时number[] | string[] | boolean[],结果变量的类型为(number | string | boolean)[]:
const a: number[] | string[] | boolean[] = [];
const b = [...a] //Type of b is now (number | string | boolean)[];
Run Code Online (Sandbox Code Playgroud)
这出乎我的意料。我本以为 的类型b是number[] | string[] | boolean[]. 有人知道为什么会出现这种情况吗?
即使原始数组的类型是数组类型的联合,数组扩展的结果似乎也将成为单个数组类型。有关更多详细信息,请参阅microsoft/TypeScript#28813。
我认为作为一个人,您会将[...a]其视为 ; 上的单个“复制”操作a。但编译器更普遍地对待它以支持诸如[1, ...a, 2]or等之类的东西。因此不会采用应该具有类型的[...a, ...a]快捷方式。[...a]typeof a
microsoft/TypeScript#28813 中的问题提到,TypeScript 中还有其他地方的联合不会像人们期望的那样向上传播出属性或向下传播到属性中。例如,采用类似的东西declare const x: {a: 0, b: 0} | {a: 1, b: 1}并将其复制到新的对象文字中将const y = {a: x.a, b: x.b}导致新的对象类型,{a: 0 | 1, b: 0 | 1}即使表面上它应该与原始对象类型相同。编译器根本不会将其分析分布到所有联合上,因为这通常会非常昂贵。(请参阅microsoft/TypeScript#25051,了解允许开发人员根据需要选择进行此类分析的拒绝建议。)对于数组扩展,这意味着没有通用机制支持[...a, ...a]被解释为number[] | string[] | boolean[].
这就是正在发生的事情以及原因。
至于替代方案,在使用可变参数元组进行数组扩展方面做了一些工作,因此如果您使用const断言来防止数组类型扩大,您将得到更接近您正在寻找的内容:
const c = [...a] as const;
// const c: readonly number[] | readonly string[] | readonly boolean[]
Run Code Online (Sandbox Code Playgroud)
或者,正如您所发现的,以及microsoft/TypeScript#28813 中提到的,您可以使用slice():
const d = a.slice();
// const d: number[] | string[] | boolean[]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1021 次 |
| 最近记录: |