TypeScript 条件类型进阶:infer 与分发实战
背景与问题界定 条件类型是 TypeScript 类型系统中最为强大也最为复杂的特性之一。它的核心语法 T extends U ? X : Y 看似简单,但在实际的工程应用中却极其容易踩坑——特别是当条件类型遇到联合类型时,TypeScript 会执行**分发(Distributive)**行为,将联合类型的每个分支分别代入条件判断。许多开发者在编写高级类型工具时,因为不理解分发机制而得到意外的类型结果。更复杂的是 infer 关键字——它允许在 extends 子句中声明类型变量,用于在模式匹配中捕获类型的某个部分。从提取函数返回类型到解构 Promise 的包裹类型,infer 是类型体操的基石。理解这些机制并将其系统化,是项目从 “能用 TypeScript” 进化到 “充分发挥类型系统能力” 的关键一步。 目标拆解与工程约束 条件类型的可预测性:任何条件类型表达式在给定相同输入时,必须输出确定且唯一的类型,不受上下文影响。 分发的显式控制:当需要禁用分发行为时,通过 [T] extends [U] 的元组包裹或使用 T & {} 明确表达意图。 infer 的单一来源:在一个条件类型中,同名 infer 变量只允许出现一次,多次出现会导致类型推导的不确定行为。 类型工具的可读性:复杂的条件类型应分解为多个命名的中间类型,每个类型附带 JSDoc 说明其计算逻辑。 方案设计 条件类型的核心机制围绕三个概念展开:分发条件类型(Distributive Conditional Types)、类型推断(infer) 和 递归条件类型(Recursive Conditional Types)。 分发是 TypeScript 条件类型的默认行为:当 T 是一个联合类型(如 string | number)时,T extends U ? X : Y 会被展开为 (string extends U ? X : Y) | (number extends U ? X : Y)。这意味着我们可以像操作普通数据一样操作类型。一个经典的应用是过滤联合类型中的某些成员: ...