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

综合案例

接下来我举一些综合性的例子,我不介绍这些例子实现的功能,大家来感受下infer的使用技巧,看看是否能一眼看出来实现的功能:

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;

这些例子中涉及到两个没有介绍的知识点:模版字面量类型递归类型,如果对这两个知识点不太懂的可以参考其他文章。这两个知识点我后面也会介绍。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容