Typescript的infer到底怎么使用?

infer 是 TypeScript 中条件类型 的一个关键字,主要用于在条件类型中进行类型推断 。它允许我们在泛型条件类型中声明一个类型变量 ,然后从其他类型中推断出这个类型

基本语法

typescript 复制代码
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

主要使用场景

1. 获取函数返回类型

typescr 复制代码
// 内置的 ReturnType 实现原理
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function foo(): string {
  return "hello";
}

type FooReturn = MyReturnType<typeof foo>; // string

2. 获取函数参数类型

typescr 复制代码
// 获取第一个参数类型
type FirstParam<T> = T extends (first: infer P, ...rest: any[]) => any ? P : never;

// 获取所有参数类型(元组)
type Params<T> = T extends (...args: infer P) => any ? P : never;

function bar(x: number, y: string): void {}

type BarFirstParam = FirstParam<typeof bar>; // number
type BarParams = Params<typeof bar>; // [number, string]

3. 获取数组/元组元素类型

typescript

typescript 复制代码
type ArrayElement<T> = T extends (infer U)[] ? U : never;

type StrArrayElement = ArrayElement<string[]>; // string
type NumArrayElement = ArrayElement<number[]>; // number

4. 获取 Promise 的解析类型

typescript 复制代码
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

type PromiseString = Promise<string>;
type Unwrapped = UnwrapPromise<PromiseString>; // string

实际应用示例

示例1:提取对象值类型

typescr 复制代码
type ValueOf<T> = T extends { [key: string]: infer V } ? V : never;

type Obj = { a: number; b: string };
type Values = ValueOf<Obj>; // number | string

示例2:提取构造函数实例类型

typescript 复制代码
type InstanceType<T> = T extends new (...args: any[]) => infer R ? R : any;

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

type AnimalInstance = InstanceType<typeof Animal>; // Animal

示例3:递归解包嵌套 Promise

typescript 复制代码
type DeepUnwrapPromise<T> = 
  T extends Promise<infer U> ? DeepUnwrapPromise<U> : T;

type NestedPromise = Promise<Promise<string>>;
type Result = DeepUnwrapPromise<NestedPromise>; // string

使用注意事项

1. 只能用在条件类型的 extends 子句中

typescr 复制代码
// ✅ 正确
type Example1<T> = T extends Array<infer U> ? U : never;

// ❌ 错误:infer 不能单独使用
type Example2<T> = infer U; // 编译错误

2. 多个 infer 可以同时使用

typescr 复制代码
type Zip<T, U> = T extends [infer A, ...infer RestT]
  ? U extends [infer B, ...infer RestU]
    ? [[A, B], ...Zip<RestT, RestU>]
    : []
  : [];

type Result = Zip<[1, 2], ['a', 'b']>; // [[1, 'a'], [2, 'b']]

3. 协变位置 vs 逆变位置

typescript 复制代码
// infer 在协变位置(返回类型)
type GetReturnType<T> = T extends () => infer R ? R : never;

// infer 在逆变位置(参数类型)
type GetArgType<T> = T extends (arg: infer A) => any ? A : never;

实战技巧

1. 类型守卫与 infer

typescr 复制代码
function isPromise<T>(value: any): value is Promise<T> {
  return value && typeof value.then === 'function';
}

async function handle<T>(input: T | Promise<T>): Promise<T> {
  if (isPromise(input)) {
    // 这里 input 被推断为 Promise<T>
    return input;
  }
  return Promise.resolve(input);
}

2. 构建实用类型工具

typescr 复制代码
// 提取所有方法的返回类型
type MethodsReturnType<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => infer R ? R : never;
};

// 提取特定属性的类型
type PropType<T, K extends keyof T> = T extends { [P in K]: infer V } ? V : never;

总结

infer 的核心作用:在条件类型中提取未知类型的内部结构。它是 TypeScript 类型系统的高级特性,常用于:

  1. 类型提取:从已有类型中提取部分类型信息
  2. 类型转换:将一个类型转换为另一种形式
  3. 类型推导:根据上下文推导出具体类型
  4. 工具类型创建:构建复杂的实用类型工具

掌握 infer 的关键是多实践,从简单的函数返回类型提取开始,逐步应用到更复杂的类型操作中。

相关推荐
HelloReader2 分钟前
Qt 项目构建入门CMake 完全指南(三)
前端
用户908324602739 分钟前
Spring AI + RAG + SSE 实现带搜索来源的智能问答完整方案
前端·后端
GISer_Jing13 分钟前
阿里开源纯前端浏览器自动化 PageAgent,[特殊字符] 浏览器自动化变天啦?
前端·人工智能·自动化·aigc·交互
清风徐来QCQ32 分钟前
js中的模板字符串
开发语言·前端·javascript
成都渲染101云渲染666637 分钟前
Houdini+Blender高效渲染方案(高配算力+全渲染器兼容)
前端·系统架构
SuperEugene1 小时前
Vue3 + Element Plus 表格实战:批量操作、行内编辑、跨页选中逻辑统一|表单与表格规范篇
开发语言·前端·javascript
极梦网络无忧1 小时前
基于 Vite + Vue3 的组件自动注册功能
前端·javascript·vue.js
Predestination王瀞潞1 小时前
5.4.3 通信->WWW万维网内容访问标准(W3C):WWW(World Wide Web) 协议架构(分层)
前端·网络·网络协议·架构·www
爱学习的程序媛2 小时前
【Web前端】优化Core Web Vitals提升用户体验
前端·ui·web·ux·用户体验
zabr2 小时前
花了 100+ 篇笔记,我整理出 了一套 AI Agent 工程完全指南
前端·后端·agent