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

相关推荐
king王一帅3 小时前
Incremark Solid 版本上线:Vue/React/Svelte/Solid 四大框架,统一体验
前端·javascript·人工智能
智航GIS8 小时前
10.4 Selenium:Web 自动化测试框架
前端·python·selenium·测试工具
前端工作日常8 小时前
我学习到的A2UI概念
前端
徐同保9 小时前
为什么修改 .gitignore 后还能提交
前端
一只小bit9 小时前
Qt 常用控件详解:按钮类 / 显示类 / 输入类属性、信号与实战示例
前端·c++·qt·gui
Mr -老鬼9 小时前
前端静态路由与动态路由:全维度总结与实践指南
前端
颜酱10 小时前
前端必备动态规划的10道经典题目
前端·后端·算法
wen__xvn10 小时前
代码随想录算法训练营DAY10第五章 栈与队列part01
java·前端·算法
大怪v11 小时前
前端佬们!!AI大势已来,未来的上限取决你的独特气质!恭请批阅!!
前端·程序员·ai编程
Mr -老鬼11 小时前
功能需求对前后端技术选型的横向建议
开发语言·前端·后端·前端框架