这似乎是为了让数组排列的结果变成单个数组类型,即使原始数组的类型是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