TS的类型编程
Typescript 支持泛型,也叫类型参数,可以对类型参数做一系列运算之后返回新的类型,这就是类型编程。
因为类型编程实现一些逻辑还是有难度的,所以被戏称为类型体操。
Typescript 类型的模式匹配
我们知道,字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 $1,$2
等引用匹配的子组。
'abc'.replace(/a(b)c/, '$1$1$1')
=> 'bbb'
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
放入不同的变量,然后和替换后的部分组成新字符串。
reverse
split
函数类型的模式匹配
参数类型
取出参数的类型是通过模式匹配拿到参数部分,放入 infer 声明的变量里返回。
返回值类型
取出返回值类型也是通过模式匹配拿到返回值部分,放入 infer 声明的类型变量里返回。
总结
类型编程是对类型参数(泛型)做一系列运算之后返回新的类型,也叫类型体操。
类型体操可以实现很多复杂的逻辑,学习起来也有一定的难度,但是掌握一些套路之后也能快速掌握。
这些套路里面最常用的就是模式匹配了,类似字符串匹配和提取子串,类型也可以通过 extends
对类型参数做匹配,把需要提取的部分保存到通过 infer
声明的局部类型变量里。
类型参数的模式匹配的套路在字符串类型、数组类型、函数类型等都有大量的应用,掌握这一个套路可以提升一大截类型体操的水平。