TS进阶之infer

收录一下,方便需要的时候查询。

参考:TS进阶之infer

主要内容:介绍下非常实用的infer的使用方法

使用介绍

条件类型的基本语法是:

 T extends U ? X : Y;

如果占位符类型 U 是一个可以被分解成几个部分的类型,譬如数组类型,元组类型,函数类型,字符串字面量类型等。这时候可以通过 infer 来获取 U 类型中某个部分的类型。

infer 语法的限制如下:

  1. infer只能在条件类型的 extends 子句中使用
  2. infer得到的类型只能在 true 语句中使用, 即 X 中使用

推断数组(或者元组)的类型

使用方法

type InferArray<T> = T extends (infer U)[] ? U : never;

(infer U) 和平时常写的 string[]number[] 等等是不是很像?这里就是通过 (infer U) 来获取数组对应的类型。

案例

type I0 = InferArray<[number, string]>; // string | number
type I1 = InferArray<string[]>; // string
type I2 = InferArray<number[]>; // number

推断数组(或者元组)第一个元素的类型

使用方法

type InferFirst<T extends unknown[]> = T extends [infer P, ...infer _] ? P : never

[infer P, ... infer _]infer P 获取的是第一个元素的类型,而 ...infer _ 获取的是数组其他剩余元素的数组类型;

特别说明下,例子汇总不需要使用其他元素的类型,所以用 _

案例

type I3 = InferFirst<[3, 2, 1]>; // 3

推断数组(或者元组)最后一个元素的类型

使用方法

type InferLast<T extends unknown[]> = T extends [... infer _, infer Last] ? Last : never;

这个和推断数组第一个元素的类型类似,...infer _ 获取的是最后一个元素之前的所有元素类型,infer Last 获取的是最后一个元素的类型。

案例

type I4 = InferLast<[3, 2, 1]>; // 1

推断函数类型的参数

使用方法

type InferParameters<T extends Function> = T extends (...args: infer R) => any ? R : never;

...args 代表的是函数参数组成的元组, infer R 代表的就是推断出来的这个函数参数组成的元组的类型。

案例

type I5 = InferParameters<((arg1: string, arg2: number) => void)>; // [string, number]

推断函数类型的返回值

使用方法

type InferReturnType<T extends Function> = T extends (...args: any) => infer R ? R : never;

和前面的推断函数类型的参数类似,=> 后面的 infer R 代表的就是推断出来的函数的返回值类型。

案例

type I6 = InferReturnType<() => string>; // string

推断 Promise 成功值的类型

使用方法

type InferPromise<T> =  T extends Promise<infer U> ? U : never;

案例

type I7 = InferPromise<Promise<string>>; // string

推断字符串字面量类型的第一个字符对应的字面量类型

使用方法

type InferString<T extends string> = T extends `${infer First}${infer _}` ? First : [];

案例

type I8 = InferString<"Johnny">; // J

综合案例

type Shift<T> = T extends [infer L, ...infer R]? [...R] : [];
type Pop<T extends any[]> = T extends [...infer L, infer R] ? [...L] : [];
type Reverse<T extends unknown[], U extends unknown[] = []> = [] extends T
  ? U
  : T extends [infer L, ...infer R]
  ? Reverse<R, [L, ...U]>
  : U;
type FlipArguments<T extends Function> = T extends (...arg: infer R) => infer S ? (...arg : Reverse<[...R]>) => S : T;
type StartsWith<T extends string, U extends string> = T extends `${U}${infer R}` ? true : false;
type TrimLeft<S extends string> = S extends `${infer L}${infer R}`
  ? L extends ' ' | '\n' | '\t'
    ? TrimLeft<R>
    : S
  : '';
type Trim<S extends string> = S extends `${' ' | '\t' | '\n'}${infer R}`
  ? Trim<R>
  : S extends `${infer L}${' ' | '\t' | '\n'}`
  ? Trim<L>
  : S;
type StringToUnion<T extends string, U = never> = T extends ''
  ? U
  : T extends `${infer L}${infer R}`
  ? StringToUnion<R, U | L>
  : U;
posted @ 2022-11-16 11:55  ESnail  阅读(191)  评论(0编辑  收藏  举报