infer,TS 类型系统的手术刀

在 TypeScript 的高级玩法里,infer 经常让初学者感到头大。它长得像关键字,用起来像正则表达式的"捕获组",还必须寄生在 extends 条件语句里。

要把这东西彻底搞清楚,我们得先拆解它的核心逻辑,再看看它在实战中到底解决了什么问题。

一、 核心概念:infer 到底是什么?

简单来说,infer 就是 "类型系统里的临时变量"

在常规的泛型中,是你告诉 TypeScript 具体的类型;而在使用 infer 的场景下,是 TypeScript 自动推断出某个位置的类型,并把它存到一个变量里供你后续使用。

语法规则:

  1. 只能在 extends 条件类型的"真"分支中使用。
  2. 配合模式匹配使用。 你给出一个"模版"(比如函数结构、数组结构),让 TS 去匹配并提取其中的零件。

二、 语义纠偏:extends 的"变脸"

很多人的困惑源于 extends 这个词。在 Class 里它是"继承",但在类型定义(尤其是配合 infer)时,它其实是 "模式匹配(Pattern Matching)"

  • Class 中的 extends:我是你的后代,我继承你的基因。
  • 类型中的 extends:我能不能塞进你这个形状的盒子里?

当你在写 T extends (infer R)[] ? R : never 时,你实际上是在对 TS 说:

"帮我看看 T 是不是一个数组。如果是,顺便把数组里装的那个东西的类型抠出来,起个临时名字叫 R。如果匹配成功,我就要这个 R。"


三、 实战场景:它能解决什么痛苦?

如果没有 infer,类型系统就是静态的、死板的。有了它,类型系统就具备了"解剖"和"重组"的能力。

1. 经典的"解包" (Unpacking)

这是最常见的用途。比如从 PromiseArrayMap 中提取内部类型。

TypeScript 复制代码
// 提取 Promise 内部的类型
type Unbox<T> = T extends Promise<infer U> ? U : T;

type Str = Unbox<Promise<string>>; // 得到 string

2. 函数全家桶 (Function Extraction)

你可以轻松拿到一个函数的返回类型、参数类型,甚至是构造函数的参数。

TypeScript 复制代码
// 提取函数第一个参数的类型
type FirstParam<T> = T extends (arg1: infer P, ...args: any[]) => any ? P : never;

function saveUser(id: number, name: string) {}
type IDType = FirstParam<typeof saveUser>; // number

3. 字符串模板的"手术刀"

这是 TS 4.1 之后的黑科技。你可以用它来拆分字符串,做一些像"驼峰转下划线"之类的类型转换。

TypeScript 复制代码
type GetExtension<T> = T extends `${string}.${infer Ext}` ? Ext : never;

type FileExt = GetExtension<"config.json">; // "json"

四、 总结:什么时候该用它?

你不需要在每一处代码都写 infer,但在以下场景,它是无可替代的神器:

  • 处理第三方库 :当你拿不到某个库内部定义的具体接口,但你能拿到它的函数或实例时,可以用 infer 反向推导出它的类型。
  • 减少重复定义 :不想为了一个返回值再去手动写一遍复杂的 interface
  • 编写通用工具库:它是构建自动化、高适配性类型系统的基石。

虽然 infer 很好用,但它会显著增加类型的理解成本。对于团队协作项目,建议只在底层工具类型(Utils)中使用它,业务代码中还是尽量保持类型声明的直观和显式。

相关推荐
懂懂tty21 小时前
React状态更新流程
前端·react.js
小码哥_常21 小时前
告别繁琐!手把手教你封装超实用Android原生Adapter基类
前端
skywalk816321 小时前
pytest测试的时候这是什么意思?Migrating <class ‘kotti.resources.File‘>
前端·python
一只蝉nahc1 天前
vue使用iframe内嵌unity模型,并且向模型传递信息,接受信息
前端·vue.js·unity
子兮曰1 天前
Bun v1.3.12 深度解析:新特性、性能优化与实战指南
前端·typescript·bun
2401_885885041 天前
易语言彩信接口怎么调用?E语言Post实现多媒体数据批量下发
前端
a1117761 天前
Three.js 的前端 WebGL 页面合集(日本 开源项目)
前端·javascript·webgl
Kk.08021 天前
项目《基于Linux下的mybash命令解释器》(一)
前端·javascript·算法
ShineWinsu1 天前
对于Linux:Ext系列文件系统的解析—下
linux·面试·笔试·文件系统··ext2·挂载分区
小李子呢02111 天前
前端八股---闭包和作用域链
前端