You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将TypeScript类型元组转换为类型交集?

如何将类型元组转换为所有类型的交集?

现有一个用于将元组类型转为所有元素类型交集的TypeScript类型工具,但在处理包含any的元组时,结果不符合预期:

type TupleToIntersection<
  Rest extends any[],
  T = Rest extends [any, ...any[]] ? Rest['0'] : never,
> = Rest extends [infer H, ...infer S] ? TupleToIntersection<S, H & T> : T


type TTest1 = TupleToIntersection<[string, any, number]> // 实际结果:any,预期结果:never!

type Test1 = string & any & number   // 结果为never(符合预期)
type Test2 = (string & any) & number // 结果为any(当前工具的执行逻辑)

问题根源

问题出在交集运算的结合顺序:当前工具采用从左到右的累积合并方式,先计算string & any得到any,再和number交集仍为any;但直接书写无括号的多类型交集时,TypeScript会按右结合逻辑处理,先计算any & number得到never,再和string交集最终为never。

解决方案

方案1:调整递归合并顺序(简单直接)

修改递归逻辑,先处理元组的剩余元素,再将当前元素与剩余元素的交集结果合并(即右结合顺序):

type TupleToIntersection<Rest extends any[]> = 
  Rest extends [infer H, ...infer S] 
    ? H & TupleToIntersection<S> 
    : unknown;

测试验证:

type TTest1 = TupleToIntersection<[string, any, number]> // never(符合预期)
type TTest2 = TupleToIntersection<[{a: 1}, {b: 2}, {c: 3}]> // {a: 1} & {b: 2} & {c: 3}

方案2:利用函数参数逆变特性(社区标准实现)

TypeScript中函数参数类型是逆变的,基于这一特性可以实现更通用的元组转交集逻辑,这也是社区广泛使用的标准写法:

type TupleToIntersection<T extends any[]> = 
  (T extends any ? (x: T) => void : never) extends (x: infer U) => void 
    ? U 
    : never;

测试验证:

type TTest1 = TupleToIntersection<[string, any, number]> // never(符合预期)
type TTest3 = TupleToIntersection<[boolean, string[], {id: number}]> // boolean & string[] & {id: number}

内容的提问来源于stack exchange,提问作者TrevTheDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:53:27