关于数组联合类型解构时触发类型分发的疑问
嗨,这个问题问得特别到位,我之前刚接触TypeScript元组的时候也被这个点绕晕过!
首先得澄清:你遇到的这个拆分联合类型的行为,和条件类型里那种“裸泛型extends时的类型分发”不是同一个机制,但本质上都是TypeScript为了精准表达类型可能性而做的展开处理。
咱们先拆解你的例子:
type A = [1] | [2] type C = [3, ...A] // 结果是 [3, 1] | [3, 2] 而非 [3, 1 | 2]
之所以会这样,是因为TypeScript在处理**元组类型中的扩展操作符(...)**时,有个固有逻辑:如果被扩展的是一个「联合类型的元组」,它会遍历这个联合的每一个成员,分别执行扩展操作,最后把所有结果重新组合成联合类型。
为什么要这么设计?其实是为了贴合运行时的实际情况:A本身代表的是两种完全不同的元组——要么是仅包含1的元组,要么是仅包含2的元组。当你用[3, ...A]组合时,运行时只会出现两种具体的元组:[3,1]或者[3,2],而不会出现一个“第二个元素可能是1或2的元组”。TypeScript的类型系统就是要精准映射这种运行时的可能性,所以才会生成元组的联合类型,而非元素为联合类型的单个元组。
你之前了解的“仅裸泛型extends时才会触发类型分发”,那个是条件类型特有的分发规则,比如:
type Distribute<T> = T extends number ? string : never type Test = Distribute<1 | 2> // 会分发成 string | string,即 string
而你遇到的元组扩展场景,属于TypeScript对元组类型扩展的独立处理逻辑,官方文档里在「元组类型(Tuple Types)」章节有提到类似行为,只是没有把它和条件类型的“类型分发”混为一谈,毕竟两者触发场景不同,但效果都是遍历联合类型的分支。
如果想得到[3, 1 | 2]这种类型,你需要把A定义成单个元组(元素为联合类型),比如type A = [1 | 2],这时候[3, ...A]就会是你预期的单个元组类型了。
内容来源于stack exchange

