TypeScript 的关键字 infer

文章类型:TypeScript

发布者:hp

发布时间:2025-03-13

一:引言

infer 是 TypeScript 中用于 ‌类型推断‌ 的关键字,主要在 ‌条件类型(extends 子句)‌ 中声明临时类型变量,通过 ‌反向推导‌ 提取复杂类型的子类型或相关类型

其核心价值在于提升类型操作的灵活性和动态性

二:定义

1:语法:若 T 符合 SomeType<U> 的结构,则 U 被自动推断为 T 中的子类型,推断成功时返回 U,失败时返回 NeverType

type Example<T> = T extends SomeType<infer U> ? U : NeverType;  

2:流程

模式匹配‌:infer 根据条件类型中的类型结构进行模式匹配,如匹配函数的参数、返回值或 Promise 的泛型参数。

‌动态提取‌:将匹配成功的子类型赋值给 infer 声明的变量(如 U),供后续类型逻辑使用

三:用法

1:动态提取类型信息

通过 infer 从泛型类型(如函数、Promise、数组等)中提取出具体的子类型(如参数、返回值、泛型参数等)

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;  
// 提取函数返回值类型,例如 ReturnType<() => number> → number ‌

2:增强条件类型的表达能力

结合 extends 条件判断,根据类型结构动态生成新类型

type UnpackPromise<T> = T extends Promise<infer U> ? U : T;  
// 解析 Promise 的泛型参数,例如 UnpackPromise<Promise<string>> → string ‌

3:简化复杂类型操作

替代手动声明类型变量,减少冗余代码,提高可读性和可维护性

type ElementType<T> = T extends (infer U)[] ? U : T;

四:场景

1:提取函数类型信息

type Parameters<T> = T extends (...args: infer P) => any ? P : never;  
// 例如 Parameters<(a: number, b: string) => void> → [number, string] ‌

2:处理异步类型(Promise 和 Async)

type AsyncResult<T> = T extends Promise<infer U> ? U : never;  
// 例如 AsyncResult<Promise<{ data: string }>> → { data: string } ‌

3:操作数组和元组类型

type FirstElement<T> = T extends [infer First, ...any[]] ? First : never;  
// 例如 FirstElement<[string, number]> → string ‌

4:递归类型推断

type Flatten<T> = T extends Array<infer U> ? Flatten<U> : T;  
// 例如 Flatten<number[][]> → number ‌

五:总结

‌1:作用域限制‌:仅能在条件类型的 extends 子句中使用,不可单独声明 ‌

2:类型匹配失败处理‌:需通过条件分支(? :)处理推断失败的情况,避免类型错误 ‌

3:‌性能优化‌:避免在深层嵌套或复杂递归场景中滥用,可能影响类型检查速度 ‌