分布式类型 (Distributive Types) 是 TypeScript 的一个特性,体现在条件类型 (T extends U ? X : Y) 的使用上。当 extends 左侧的类型变量是一个联合类型时,TypeScript 会将条件应用于联合中的每个元素。
示例:
// "Test<A> | Test<B> | Test<C>" type Test<T> = T extends string ? () => string : () => number; type Result = Test<'A' | 'B' | 'C'>;
这里 Result 将分布为:
应用场景 — 用于编写通用 API、对联合类型进行操作,例如过滤或模式匹配。
特点:
[T] 中,则不会发生分布。这是一种“禁用”分布的方法。问题: 类型 T[] extends number[] ? true : false 会是分布式的吗?
正确答案: 不会,分布仅发生在左侧的类型变量没有被数组或元组包裹的情况下。例如,条件类型 T extends number ? ... 会进行分布,但 T[] extends number[] ? ... 则不会。
故事
项目: 一个用于验证 React 组件的 props 的库。希望实现一个将 union props 转换为严格接口的类型,但因为不理解分布,导致类型变得出乎意料的复杂(union 成员的属性混合在一起)。最后通过添加包裹
[T]来修正,使分布不再发生。
故事
项目: 将所有事件类型设计为一个函数处理程序。在条件类型中,期望函数能通过分布接收每种事件类型,但由于未显式使用导致处理不正确,导致参数类型错误(使用了 union 而不是每种类型单独调用)。
故事
项目: 在创建自定义工具类型(如 Exclude、Extract)时忘记了对于元组和数组不会发生分布。结果,Exclude 类型在数组中不起作用(例如,类型
Exclude<["a"|"b"], "b">不会删除 "b")。