TypeScript类型系统进阶:条件类型与infer关键字详解
字数 733 2025-11-10 08:13:52
TypeScript类型系统进阶:条件类型与infer关键字详解
一、类型系统的背景与需求
TypeScript的类型系统不仅提供基础类型注解,还支持类型编程。条件类型(Conditional Types)是类型系统中的高级特性,允许根据类型关系动态推导类型,解决复杂泛型场景下的类型推断问题。
二、条件类型基础语法
T extends U ? X : Y
- 语义:若类型T可赋值给类型U,则结果为类型X,否则为类型Y
- 示例:
type IsString<T> = T extends string ? true : false
type A = IsString<'hello'> // true
type B = IsString<123> // false
三、分布式条件类型
当条件类型作用于泛型参数且T是联合类型时,会发生分布式分发:
type ToArray<T> = T extends any ? T[] : never
type Result = ToArray<string | number> // string[] | number[]
执行过程:
- 拆解联合类型:
string | number - 分别应用条件:
string extends any ? string[] : never→string[] - 合并结果:
string[] | number[]
四、infer关键字原理
infer用于在条件类型中声明临时类型变量,实现模式匹配:
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never
执行机制:
- 检查T是否匹配函数类型模式
- 若匹配,将返回值类型推断为R
- 示例:
type Func = (x: number) => boolean
type Result = GetReturnType<Func> // boolean
五、infer进阶应用场景
- 提取Promise包裹类型:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
type A = UnwrapPromise<Promise<string>> // string
- 提取数组元素类型(递归处理):
type Flatten<T> = T extends Array<infer U> ? Flatten<U> : T
type B = Flatten<number[][]> // number
- 提取函数参数类型:
type Parameters<T> = T extends (...args: infer P) => any ? P : never
type C = Parameters<(a: string, b: number) => void> // [string, number]
六、条件类型中的类型推断限制
- infer只能在条件类型的true分支使用
- 同一类型变量infer必须位置一致:
type MultipleInfer<T> = T extends { a: infer U, b: infer U } ? U : never
type D = MultipleInfer<{ a: string, b: string }> // string
type E = MultipleInfer<{ a: string, b: number }> // string | number
七、实战案例:实现高级工具类型
- 替换函数返回值类型:
type ReplaceReturnType<T, R> = T extends (...args: infer P) => any ? (...args: P) => R : never
type NewFunc = ReplaceReturnType<(x: number) => string, boolean> // (x: number) => boolean
- 递归展开只读属性:
type DeepMutable<T> = {
-readonly [P in keyof T]: T[P] extends object ? DeepMutable<T[P]> : T[P]
}
八、编译时类型运算的本质
条件类型和infer在编译阶段进行类型运算,不会产生运行时开销。TypeScript编译器通过类型关系推导,在保证类型安全的同时提供灵活的类型编程能力。
通过条件类型与infer的组合使用,可以构建类型安全的抽象,实现智能的类型推导,显著提升类型系统的表达能力和开发体验。