T extends U ? X : Y 条件类型
最后更新:2026-10-22
T extends U ? X : Y 条件类型
条件类型让类型做"选择题":T extends U ? X : Y——满足条件选 X,否则选 Y。它把运行时的三元判断搬到类型层,配合泛型可以写出随输入类型变化的返回类型。
| 分组 | 泛型 |
|---|---|
| 类型 | 语法 |
| 严格模式 | 不需要 |
ℹ️ 说明 编辑器将 TypeScript 转译为 JavaScript 后运行(不做类型检查);类型检查结果见示例 Output。
📝 语法
type Wrapped<T> = T extends string
? { kind: "str"; value: T }
: { kind: "num"; value: number };
type A = Wrapped<string>; // { kind: "str"; value: string }
type B = Wrapped<number>; // { kind: "num"; value: number }
// 联合类型会分布式展开(分配条件类型)
type ToArray<T> = T extends unknown ? T[] : never;
⚙️ 参数
| T extends U | 条件判断:结构兼容则取真分支 |
|---|---|
| ? X : Y | 两个分支:都是完整的类型表达式,可继续嵌套条件 |
返回值:条件类型是纯类型层运算,不产生运行时代码;结果取决于泛型实参是否满足 extends。
▶ 示例
修改下面的代码,点击试一试查看转译运行结果:
输出:
{"kind":"str","value":"hi"}
{"kind":"num","value":7}
(转译后运行输出;wrap(true) 会得到编译错误——没有任何重载接受 boolean)
💡 要点
ℹ️ 说明 裸类型参数遇上联合类型会"分配":ToArray<string | number> 得到 string[] | number[],而不是 (string | number)[]——这是条件类型的分布式特性,也是 Exclude 的实现原理。
💡 提示 never 在条件类型里是"过滤掉"的信号:type NonNull<T> = T extends null | undefined ? never : T 分发后自动剔除空值成员。
⚠️ 注意 条件类型套三层以上可读性骤降:能用映射类型、索引访问解决的,别上条件类型;嵌套时用中间 type 别名拆步。
🏷️ 相关泛型
💡 相关案例
更多案例即将上线。
📚 相关教程
❓ 常见问题
Q 条件类型和函数重载怎么选?
A 类型逻辑简单(一两个分支)用条件类型写一个签名;分支多或要精确到字面量时重载更直观。两者可以混用(示例就是这样)。
Q 为什么 T extends string 对 string | number 也"成立"了?
A 那是分布式在起作用:联合被拆开逐个判断再合并。想整体判断(不分配)用 [T] extends [string] 的元组包裹写法。
Q 条件类型能用在函数参数上吗?
A 可以但需谨慎:参数位置的条件类型会让调用方推断变得微妙;更常见的做法是参数用泛型、返回值用条件类型联动。