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 里各种类型体操的基础,基于它可以实现各种「高级」类型。

相关推荐
常乐我净61623 分钟前
十、路由和导航
前端
米诺zuo25 分钟前
MUI sx prop 中的响应式适配
前端
周尛先森26 分钟前
都React 19了,他到底带来了什么?
前端
洞窝技术31 分钟前
一键屏蔽某国IP访问实战
前端·nginx·node.js
fruge43 分钟前
前端自动化脚本:用 Node.js 写批量处理工具(图片压缩、文件重命名)
前端·node.js·自动化
Jolyne_1 小时前
antd Image base64缓存 + loading 态优化方案
前端
BINGCHN1 小时前
NSSCTF每日一练 SWPUCTF2021 include--web
android·前端·android studio
Z***u6592 小时前
前端性能测试实践
前端
xhxxx2 小时前
prototype 是遗产,proto 是族谱:一文吃透 JS 原型链
前端·javascript