TypeScript 里 infer 常见用法

1 什么是「infer」

1.1 概念

infer 只能在 条件类型(conditional types) 中使用,用来 在类型推断时声明一个待推断的类型变量

语法为:

typescript 复制代码
T extends SomeType<infer U> ? U : never

可以这么理解:

  • 如果 T 能匹配 SomeType<某个类型> 的结构
  • 那么把内部类型推断为 U
  • 然后返回 U

1.2 特点

1.2.1 只能在 extends ? : 中使用

不能单独写,比如下边这么写就是错的:

typescript 复制代码
type A = infer T; 

1.2.2 右侧的类型结构必须能匹配

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

type B = A<[string]>; // string
type C = A<string>;   // never

2 基本用法

2.1 提取函数返回值类型

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

type A = ReturnType<() => number>;
// A = number

infer R 就是 推断函数的返回值类型

2.2 提取参数类型

typescript 复制代码
type FirstArg<T> = T extends (arg: infer P, ...args: any[]) => any ? P : never;

type A = FirstArg<(x: string, y: number) => void>;
// A = string

2.3 提取数组元素类型

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

type A = ElementOf<string[]>; 
// A = string

2.4 提取 tuple 的某个元素

typescript 复制代码
type First<T> = T extends [infer F, ...any[]] ? F : never;

type A = First<[string, number, boolean]>;
// A = string

在这个例子中,我们提取的是 tuple 的第一个元素。

2.5 提取对象中某个 key 的类型

typescript 复制代码
type PropType<T, K extends keyof T> = 
  T extends { [Key in K]: infer R } 
    ? R 
    : never;

type A = PropType<{name: string; age: number}, 'age'>;
// A = number

2.6 对象路径提取

typescript 复制代码
type Path<T> = {
    [K in keyof T]: 
        T[K] extends object 
          ? `${string & K}.${Path<T[K]>}`
          : `${string & K}`;
}[keyof T];

假设说我们有这么一个类型:

typescript 复制代码
type User = {
  id: number;
  name: {
    first: string;
    last: string;
  };
  address: {
    city: string;
    location: {
      lat: number;
      lng: number;
    };
  };
};

执行 Path

typescript 复制代码
type UserPath = Path<User>;

之后得到的结果展开就是:

typescript 复制代码
type UserPath =
  | "id"
  | "name.first"
  | "name.last"
  | "address.city"
  | "address.location.lat"
  | "address.location.lng";

3 总结

本文总结了 TypeScript 中 infer 的常见用法,可以说 infer 是 TypeScript 里各种类型体操的基础,基于它可以实现各种「高级」类型。

相关推荐
2301_780669869 小时前
Vue(入门配置、常用指令)、Ajax、Axios
前端·vue.js·ajax·javaweb
码农幻想梦9 小时前
Vue3入门到实战【尚硅谷】
前端·vue
hudou_k9 小时前
利用WebNaket实现Web应用直接访问硬件设备
前端
吃茄子的猫9 小时前
若依框架根据当前登录人信息,显示不同的静态公司logo
前端·vue
LZQ <=小氣鬼=>9 小时前
React + Ant Design (antd) 国际化完整实战教程
前端·react.js·前端框架·antd·moment
星海拾遗10 小时前
react源码从入门到入定
前端·javascript·react.js
Charlie_lll10 小时前
学习Three.js–星环粒子(ShaderMaterial)
前端·three.js
wuhen_n10 小时前
JavaScript事件循环(下) - requestAnimationFrame与Web Workers
开发语言·前端·javascript
我是ed.10 小时前
Vue3 音频标注插件 wavesurfer
前端·vue.js·音视频
铁蛋AI编程实战10 小时前
Gemini in Chrome 全实战:解锁+API调用+自定义扩展+本地推理
前端·人工智能·chrome