TypeScript `infer` 关键字详解(从概念到实战)
目标读者:有一定 TypeScript 基础(了解泛型、条件类型)的同学,希望理解
infer
在类型体操中的作用。
目录
-
什么是
infer
-
基础用法:在条件类型中推断类型
-
常见场景与示例
- 提取函数返回值类型
- 提取参数类型
- 提取 Promise 内的类型
- 提取数组元素类型
-
内置工具类型中的应用(ReturnType、Parameters 等)
-
实战:封装工具类型
UnpackPromise<T>
First<T>
、Last<T>
ElementType<T>
-
进阶技巧:多层 infer、递归推断
-
总结与学习建议
1. 什么是 infer
infer
是 TypeScript 在 条件类型 中的关键字。- 它的作用是:在类型推导过程中,声明一个待推断的类型变量。
简单来说:infer
就是“让 TS 在这里自动推断类型,并把它存下来”。
2. 基础用法
最简单的形式:
type Foo<T> = T extends Array<infer U> ? U : T;
解释:
- 如果
T
是数组(Array<...>
),就提取里面的元素类型U
。 - 否则返回
T
本身。
示例:
type A = Foo<string[]>; // string
type B = Foo<number>; // number
3. 常见场景与示例
3.1 提取函数返回值类型
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;function add(a: number, b: number) {return a + b;
}type R = MyReturnType<typeof add>; // number
3.2 提取参数类型
type MyParameters<T> = T extends (...args: infer P) => any ? P : never;function greet(name: string, age: number) {}type Params = MyParameters<typeof greet>; // [string, number]
3.3 提取 Promise 内的类型
type UnpackPromise<T> = T extends Promise<infer U> ? U : T;async function fetchUser() {return { id: 1, name: 'Alice' };
}type User = UnpackPromise<ReturnType<typeof fetchUser>>;
// { id: number; name: string }
3.4 提取数组元素类型
type ElementType<T> = T extends (infer U)[] ? U : never;type E1 = ElementType<string[]>; // string
type E2 = ElementType<number[]>; // number
4. 内置工具类型中的应用
其实 TS 内置很多工具类型都是用 infer
实现的:
type ReturnType<T extends (...args: any) => any> =T extends (...args: any) => infer R ? R : any;type Parameters<T extends (...args: any) => any> =T extends (...args: infer P) => any ? P : never;
举例:
function hello(a: string, b: number) { return true; }type R = ReturnType<typeof hello>; // boolean
type P = Parameters<typeof hello>; // [string, number]
5. 实战:封装工具类型
5.1 UnpackPromise<T>
提取 Promise 内的类型:
type UnpackPromise<T> = T extends Promise<infer U> ? U : T;const p: Promise<string> = Promise.resolve('hi');
type R = UnpackPromise<typeof p>; // string
5.2 First<T>
(数组第一个元素)
type First<T extends any[]> = T extends [infer F, ...any[]] ? F : never;type F1 = First<[1, 2, 3]>; // 1
type F2 = First<[]>; // never
5.3 Last<T>
(数组最后一个元素)
type Last<T extends any[]> = T extends [...any[], infer L] ? L : never;type L1 = Last<[1, 2, 3]>; // 3
type L2 = Last<[]>; // never
5.4 ElementType<T>
(提取数组元素)
type ElementType<T> = T extends (infer U)[] ? U : never;type E = ElementType<[string, number]>; // string | number
6. 进阶技巧:多层 infer、递归推断
6.1 多层 infer
可以在嵌套条件类型中多次使用 infer
:
type DeepUnpack<T> =T extends Promise<infer U>? U extends Promise<infer K>? K: U: T;// Promise<Promise<number>> → number
type X = DeepUnpack<Promise<Promise<number>>>;
6.2 递归推断
甚至可以递归定义:
type DeepUnpackAll<T> =T extends Promise<infer U>? DeepUnpackAll<U>: T;// Promise<Promise<Promise<string>>> → string
type Y = DeepUnpackAll<Promise<Promise<Promise<string>>>>;
7. 总结与学习建议
infer
必须出现在 条件类型 中。- 它的主要作用是:临时声明一个类型变量,捕获 TS 推断出来的类型。
- 常见应用场景:提取函数参数/返回值、解包 Promise、数组元素类型。
- 掌握
infer
后,你能看懂并写出更多高级工具类型,是进阶 TS 的必经之路。
下一步学习:
- 条件类型与分布式条件类型(
T extends U ? X : Y
) - 内置工具类型源码(看一看
Omit
、Pick
、InstanceType
) - 玩转类型体操题库(练习
TupleToUnion
、UnionToIntersection
等)