深圳幻海软件技术有限公司 欢迎您!

模式匹配-让你TS类型体操水平暴增的套路

2023-02-28

Typescript支持泛型,也叫类型参数,可以对类型参数做一系列运算之后返回新的类型,这就是类型编程。因为类型编程实现一些逻辑还是有难度的,所以被戏称为类型体操。社区有用Typescript类型实现Lisp解释器、实现象棋等案例的(知乎可以搜到),这足够说明了Typescript类型可以实现各种复

Typescript 支持泛型,也叫类型参数,可以对类型参数做一系列运算之后返回新的类型,这就是类型编程。

因为类型编程实现一些逻辑还是有难度的,所以被戏称为类型体操。

社区有用 Typescript 类型实现 Lisp 解释器、实现象棋等案例的(知乎可以搜到),这足够说明了 Typescript 类型可以实现各种复杂逻辑。

那 Typescript 类型体操这么难,有没有什么快速掌握的方式呢?

确实有,我总结了一些套路,可以快速提升 ts 类型体操水平。比如今天要讲的套路--模式匹配。

Typescript 类型的模式匹配

我们知道,字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 $1,$2 等引用匹配的子组。

Typescript 的类型也同样可以做模式匹配。

比如,提取 Promise 的值的类型:

我们通过 extends 对传入的类型参数 T 做模式匹配,其中 value 部分是需要提取的,通过 infer 类声明一个局部变量 R 来保存,如果匹配,就返回匹配到的 R,否则就返回 never 代表没匹配到。

这就是 Typescript 类型的模式匹配。

小结一下: Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数等类型里的应用。

数组类型的模式匹配

pop

pop 是去掉最后一个元素,可以通过模式匹配来实现:

我们通过模式匹配取出最后一个元素的类型和前面的元素的类型,分别用 infer 放入不同的变量里,然后构造一个新的数组类型返回。

shift

同样,shift 是去掉最开始的元素,也是类似的匹配方式来实现:

 

字符串类型的模式匹配

trim

trim 是去掉前后的空格、制表符、换行符,那么就通过模式匹配取出后面的字符,通过 infer 放入新的变量返回就行。

先实现 TrimLeft:

如果匹配就继续递归 TrimLeft,直到前面没有空白字符。

再实现 TrimRight:

然后两者结合,就是 Trim:

replace

replace 是替换字符串中的一部分,可以通过模式匹配取出这段字符串前后的子串,通过 infer 放入不同的变量,然后和替换后的部分组成新字符串。

函数类型的模式匹配

参数类型

取出参数的类型是通过模式匹配拿到参数部分,放入 infer 声明的变量里返回。

返回值类型

取出返回值类型也是通过模式匹配拿到返回值部分,放入 infer 声明的类型变量里返回。

总结

类型编程是对类型参数(泛型)做一系列运算之后返回新的类型,也叫类型体操。

类型体操可以实现很多复杂的逻辑,学习起来也有一定的难度,但是掌握一些套路之后也能快速掌握。

这些套路里面最常用的就是模式匹配了,类似字符串匹配和提取子串,类型也可以通过 extends 对类型参数做匹配,把需要提取的部分保存到通过 infer 声明的局部类型变量里。

类型参数的模式匹配的套路在字符串类型、数组类型、函数类型等都有大量的应用,掌握这一个套路可以提升一大截类型体操的水平。