infer 关键字必须配合条件类型使用,用于在 T extends Promise<infer U> 中推导 Promise 的内部类型 U;基础类型 UnwrapPromise<T> 解一层,DeepUnwrap<T> 递归解多层;常用于自动提取异步函数返回值类型。

在 TypeScript 中,infer 关键字必须配合条件类型(conditional type)使用,它的作用是在条件类型中“推导”出某个类型 —— 类似于函数参数的“解构”,但发生在类型层面。要提取 Promise<T> 中的 T,核心思路是:用条件类型判断是否为 Promise<U>,若匹配,则用 infer U 把内部类型捕获出来。
基础写法:用 infer 提取 Promise 的 resolve 类型
最简实现如下:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
说明:
-
T extends Promise<infer U>表示 “如果 T 是 Promise 类型,且其泛型参数可被推导为某个类型 U”; - 一旦匹配成功,
U就是 Promise 内部的 resolve 类型(比如Promise<string>→U是string); - 不匹配时(如传入
number或Array<any>),直接返回原类型T,保证类型安全和兼容性。
支持多层嵌套 Promise(如 Promise<Promise<number>>)
上面的类型只解一层。若需递归展开所有 Promise 包裹,可配合类型递归:
type DeepUnwrap<T> = T extends Promise<infer U> ? DeepUnwrap<U> : T;
例如:
-
DeepUnwrap<Promise<Promise<boolean>>>→boolean -
DeepUnwrap<Promise<{ id: number }>>→{ id: number } -
DeepUnwrap<string>→string(无 Promise,直接返回)
实际使用场景示例
常用于封装异步工具类型,比如统一处理 API 返回值:
async function fetchUser(): Promise<{ name: string; age: number }> { ... }
type UserType = UnwrapPromise<ReturnType<typeof fetchUser>>; // → { name: string; age: number }
这样无需手动写 { name: string; age: number },类型自动从函数签名中提取,避免重复和不一致。
注意事项与边界情况
以下几点容易踩坑,需留意:
-
infer只能在条件类型的extends左侧出现,不能出现在右侧或普通类型别名中; - 若 Promise 是联合类型(如
Promise<string | number>),infer U会正确推导为string | number; - 不支持提取
PromiseLike或自定义 thenable 类型(除非显式扩展条件); - TypeScript 4.1+ 支持在模板字面量类型、映射类型中使用
infer,但 Promise 解包场景中标准条件类型已足够。


















