在 TypeScript 中,条件类型具有一种特殊的行为:当泛型参数是联合类型时,条件类型会对联合类型的每个成员逐一应用条件,而不是整体作为一个类型处理。这种行为称为 **分布式条件类型(distributive conditional types)**。
条件类型的语法
T extends U ? X : Y
这里,T 是被判断的类型,U 是条件类型的基准。如果 T 是 U 的子类型,那么返回 X,否则返回 Y。
分布式特性
分布式特性只有在 T 是一个 裸露的泛型类型(裸类型参数) 时才会生效。例如:
type Distributed<T> = T extends U ? X : Y;
如果 T 是一个联合类型,如 A | B | C,TypeScript 会自动将其分解成 A、B 和 C,分别代入条件类型计算。
结合原代码分析
在 UnionToIntersection 的定义中:
T extends any ? (x: T) => any : never
- 这里的
T可能是一个联合类型,例如{ a: string } | { b: number }。 T extends any触发了分布式条件类型特性。- 因此,对于联合类型
T,TypeScript 会将其分解为{ a: string }和{ b: number },然后分别计算条件类型。
这使得 T 被遍历为联合类型的每一个成员,而不是整体作为一个类型。
具体执行过程
假设 T 是 { a: string } | { b: number }:
-
TypeScript 会将
T的联合类型拆分:- 第一次计算,
T被代入为{ a: string }:(x: { a: string }) => any - 第二次计算,
T被代入为{ b: number }:(x: { b: number }) => any
- 第一次计算,
-
这两次计算的结果会合并成一个新的联合类型:
(x: { a: string }) => any | (x: { b: number }) => any
为什么这样设计?
TypeScript 的分布式特性在处理联合类型时极为灵活。通过 T extends any,我们可以拆分并单独操作联合类型的每个成员。配合推断 infer 和交叉类型操作,我们可以将这些单独的结果重新组合成想要的类型。
进一步示例
以下代码更直观地展示了分布式条件类型的作用:
type Example<T> = T extends any ? { value: T } : never;
// 如果传入一个联合类型
type Result = Example<string | number>;
// TypeScript 会分布计算:
// - 当 T = string 时,结果为 { value: string }
// - 当 T = number 时,结果为 { value: number }
// 最终 Result 为 { value: string } | { value: number }
这种机制也是 UnionToIntersection 能够逐个处理联合类型并最终生成交叉类型的核心原因。
总结
T extends any在联合类型时触发 分布式条件类型。- TypeScript 会将联合类型拆分为单个成员,分别应用条件类型逻辑。
- 在
UnionToIntersection中,这一特性用于对联合类型的每个成员生成函数类型(x: T) => any,然后再利用交叉类型将它们合并。
















