类型级条件
使用条件类型表达式根据类型进行分支。
类型级条件 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。
类型级条件语句
类型语言通过条件类型获得了分支能力。语法 T extends U ? X : Y 的含义是:如果 T 可赋值给 U,结果就是 X,否则就是 Y。
这相当于类型级的 if / else 表达式。
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"extends 表示可赋值
这里的测试不是相等性判断。当预期类型为 U 时,如果可以使用类型为 T 的值,则 T extends U 为真。字面量类型可以赋值给其基础类型。
type T1 = "hello" extends string ? true : false; // true
type T2 = string extends "hello" ? true : false; // false
type T3 = 42 extends number ? true : false; // true选择结果类型
条件类型可以让一个泛型根据输入返回不同的结构。在这里,Wrap 对数组和标量采用了不同的封装方式。
type Wrap<T> = T extends unknown[]
? { list: T }
: { value: T };
type A = Wrap<number>; // { value: number }
type B = Wrap<string[]>; // { list: string[] }筛选为 never
一种常见技巧是在某个分支返回 never。never 表示“没有值”,稍后可以利用它从联合类型中移除成员。
type OnlyStrings<T> = T extends string ? T : never;
type A = OnlyStrings<string>; // string
type B = OnlyStrings<number>; // never使用类型推断
真正强大的功能来自 infer 关键字。在条件类型中,infer 会引入一个新的类型变量,用来捕获匹配类型的一部分。
这里我们捕获数组的元素类型。
type ElementType<T> = T extends (infer U)[] ? U : never;
type A = ElementType<number[]>; // number
type B = ElementType<string[]>; // string推断函数结果
您可以将 infer 放在模式中的任意位置。要提取函数返回类型,请推断箭头之后的部分。内置的 ReturnType 正是这样实现的。
type MyReturn<T> = T extends (...args: any[]) => infer R ? R : never;
type A = MyReturn<() => number>; // number
type B = MyReturn<(x: string) => boolean>; // boolean推断多个部分
一个条件类型可以同时引入多个 infer 变量。在这里,我们同时提取元组的第一个元素和其余部分。
type FirstRest<T> = T extends [infer H, ...infer R]
? { head: H; rest: R }
: never;
type A = FirstRest<[1, 2, 3]>;
// { head: 1; rest: [2, 3] }嵌套条件
条件类型的嵌套方式与链式 else if 完全一样。一个条件类型的 else 分支本身可以是另一个条件类型,从而形成决策阶梯。
type Describe<T> =
T extends string ? "text" :
T extends number ? "num" :
T extends boolean ? "flag" :
"other";
type A = Describe<number>; // "num"
type B = Describe<null>; // "other"将条件作为守卫
使用条件类型在提取数据之前验证其结构。如果输入不匹配,则回退到 never,这样就能显现误用。
type GetName<T> = T extends { name: infer N } ? N : never;
type A = GetName<{ name: string }>; // string
type B = GetName<{ age: number }>; // never组合条件
您可以通过嵌套条件来要求多个条件同时满足。在这里,某个类型必须既是对象,又具有 id,才能通过检查。
type RequireId<T> =
T extends object
? T extends { id: unknown } ? T : never
: never;
type A = RequireId<{ id: 1; x: 2 }>; // { id: 1; x: 2 }
type B = RequireId<{ x: 2 }>; // never条件类型无处不在
大多数内置工具类型底层都是条件类型:NonNullable、Extract、Exclude、Parameters 和 ReturnType。理解 extends ? : 就能掌握它们全部。
type MyNonNullable<T> = T extends null | undefined ? never : T;
type A = MyNonNullable<string | null>; // string快速检查
测试您对条件类型和 infer 的理解。
回顾
条件类型为类型语言提供了条件分支和模式匹配。
T extends U ? X : Y根据可赋值性进行分支。infer会将匹配的部分捕获到新的变量中。- 条件类型可以嵌套,形成决策阶梯。
- 返回
never可以筛选掉成员。
接下来:让条件类型递归调用自身,实现递归。
常见问题解答
「类型级条件」课时是免费的吗?
是的 — 「类型级条件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。
「类型级条件」这节课中我会学到什么?
使用条件类型表达式根据类型进行分支。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 TypeScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「类型级条件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 TypeScript Academy 课中编写并运行代码吗?
能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。