乐趣区

关于typescript:快速掌握-TypeScript-新语法infer-extends

咱们晓得,TypeScript 反对 infer 来提取类型的一部分,通过模式匹配的形式。
比方元组类型提取最初一个元素的类型:
type Last<Arr extends unknown[]> =

Arr extends [...infer rest,infer Ele]
    ? Ele 
    : never;

复制代码

比方函数提取返回值类型:
type GetReturnType<Func extends Function> =

Func extends (...args: any[]) => infer ReturnType 
    ? ReturnType 
    : never;

复制代码

比方字符串提取一部分,而后替换:
type ReplaceStr<

Str extends string,
From extends string,
To extends string

= Str extends ${infer Prefix}${From}${infer Suffix}

    ? `${Prefix}${To}${Suffix}` : Str;

复制代码

模式匹配就是通过一个类型匹配一个模式类型,须要提取的局部通过 infer 申明一个局部变量,这样就能从局部变量里拿到提取的类型。
infer 的模式匹配用法还是挺好了解的。
然而 infer 有一个问题,比方这样:

从 string 数组中提取的元素,默认会推导为 unknown 类型,这就导致了不能间接把它当 string 用:

那怎么办呢?
之前的解决形式是这样的:

加一层判断,这样 Last 就推导为 string 类型了。
或者也能够和 string 取穿插类型:

这样也能够作为 string 来用。
然而咱们明明晓得这里就是 string,却还须要 & string 或者 xxx extends string 来转换一次,这也太麻烦了。
TS 也晓得有这个问题,所以在 4.7 就引入了新语法:infer extends。
当初咱们能够这样写:

infer 的时候加上 extends 来束缚推导的类型,这样推导出的就不再是 unknown 了,而是束缚的类型。
试一下
这个语法是 TS 4.7 引入的,在 4.8 又欠缺了一下。
比方这样一个类型:
type NumInfer<Str> =

Str extends `${infer Num extends number}`
    ? Num
    : never;

复制代码
在 4.7 的时候推导后果是这样:

而 4.8 就是这样了:

也就是说 4.7 的时候推导出的就是 extends 束缚的类型,然而 4.8 的时候,如果是根底类型,会推导出字面量类型。
有了这个语法之后,除了能简化类型编程的逻辑之外,也能实现一些之前实现不了的性能:
比方提取枚举的值的类型:
enum Code {

a = 111,
b = 222,
c = "abc"

}
复制代码
咱们都是这样写:

然而有的值明明是数字,却被作为了字符串,所以要再解决一下,转换成数字类型,这时候就能够用 infer extends 了:
type StrToNum<Str> =
Str extends ${infer Num extends number}

? Num
: Str

复制代码
做完 string 到 number 的转换,就拿到了咱们想要的后果:

这就是 infer extends 的第二个作用。
解决 string 转 number 之外,也能够转 boolean、null 等类型:

试一下
总结
Typescript 反对 infer 类型,能够通过模式匹配的形式,提取一部分类型返回。
然而 infer 提取出的类型是 unknown,前面用的时候须要相似和 string 取穿插类型,或者 xxx extends string 这样的形式来转换成别的类型来用。这样比拟麻烦。
所以 TS 4.7 实现了 infer extends 的语法,能够指定推导出的类型,这样简化了类型编程。
而且,infer extends 还能够用来做类型转换,比方 string 转 number、转 boolean 等。
要留神的是,4.7 的时候,推导出的只是 extends 束缚的类型,比方 number、boolean,然而 4.8 就能推导出字面量类型了,比方 1、2、true、false 这种。
有了 infer extends,岂但能简化类型编程,还能实现一些之前很难实现的类型转换,是很有用的一个新语法。

退出移动版