在Typescript中,当扩展类型为number[] | string[] | boolean[]的变量时,得到的变量类型为(number | string | boolean)[]:

const a: number[] | string[] | boolean[] = [];

const b = [...a] //Type of b is now (number | string | boolean)[];

TS Playground

这对我来说是出乎意料的.我本以为bnumber[] | string[] | boolean[].有人知道为什么会这样吗?

推荐答案

这似乎是为了让数组排列的结果变成单个数组类型,即使原始数组的类型是union个数组类型.详见microsoft/TypeScript#28813.

我认为,作为一个人,你看[...a],把它看作是对a的一次"复制"操作;但编译器更普遍地对待它,以支持[1, ...a, 2][...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},尽管表面上它应该与原始对象类型相同.编译器只是不将其分析分布到所有联合体,因为这通常会非常昂贵.(关于允许开发者根据需要 Select 进行此类分析的建议,请参见microsoft/TypeScript#25051.)对于数组排列,这意味着没有通用机制来支持将[...a, ...a]解释为number[] | string[] | boolean[].

这就是发生的事情和原因.


至于替代方案,在使用variadic tuples排列的数组上做了一些工作,因此如果您使用const assertion来防止数组类型的扩大,您将获得更接近您所需的内容:

const c = [...a] as const;
// const c: readonly number[] | readonly string[] | readonly boolean[]

或者,正如你所发现的,作为mentioned in microsoft/TypeScript#28813,你可以使用slice():

const d = a.slice();
// const d: number[] | string[] | boolean[]

Playground link to code

Typescript相关问答推荐

使用新控制流的FormArray内部的Angular FormGroup

React组件数组及其props 的类型定义

您可以创建一个类型来表示打字员吗

参数类型undefined不能分配给参数类型字符串|未定义

动态调用类型化函数

如何在排版中正确键入中间件链和控制器链

在动态对话框中使用STEP组件实现布线

泛型函数中输入参数类型的推断问题

通配符路径与每条路径一起显示

诡异的文字类型--S为物语的关键

以Angular 执行其他组件的函数

React router 6(数据路由)使用数据重定向

有没有办法取消分发元组的联合?

将带有样式的Reaction组件导入到Pages文件夹时不起作用

Typescript将键数组映射到属性数组

如何在Angular /字体中访问API响应的子元素?

任何导航器都未处理有效负载为";params";:{";roomId";:";...";}}的导航操作

如何创建由一个帐户签名但使用另一个帐户支付的Hedera交易

什么';是并类型A|B的点,其中B是A的子类?

如何避免TS2322;类型any不可分配给类型never;使用索引访问时