体操就是做锻炼,给你的大脑做锻炼
有没有什么实际的意义呢?我觉得没有,工作中用不到,只是为了锻炼而已
if else
JS:
if (A <= B) {
return true
} else {
return false
}
TS:
type A = 1
type B = 1 | 2
type Result = A extends B ? true : false
加一点复杂
JS:
if (A<= B && C<= D) {
...
} else {
...
}
TS:
type A = 1
type B = 1 | 2
type C = 3
type D = 3 | 4
type Result = A extends B
? C extends D
? 'true, true'
: 'true, false'
: C extends D
? 'false, true'
: 'false, false'
看的出来,没有 if else,TS 的代码很难看
这就是 TS 类型体操的蛋疼之处,并不是逻辑复杂,而是看起来复杂
判断是否是元组
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr['length'] extends 0 ? true : false
type Result = IsEmptyArray<A> // TODO: true
infer
还是以上面判断是否为元组的栗子:
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr extends [...inter X[], inter D] ? true : false
type Result = IsEmptyArray<A> // TODO: true
这里用 inter “引用”(可以把它当做 var),等价于:
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr extends [...unknown[], unknown] ? true : false
type Result = IsEmptyArray<A> // TODO: true
递归
等价于 for 循环,但是在 TS 中递归有层数限制(不多),有兴趣动手可以测试一下
type A = ['ji', 'ni', 'tai', 'mei']
type Reverse<Arr extends unknown[]> =
Arr extends [...infer Rest, inter Last]
? [Last, ...Reverse<Rest>]
: Arr
tytpe Result = Reverse<A> // TODO: ['mei', 'tai', 'ni', 'ji']
模式匹配
合并元组
type A = [1, 2]
type B = [3, string]
type C = [...A, ...B]
获取元组的最后一项
type Arr = [1, 2, 3, 4]
type Last<T extends unknown[]> = T extends [...Rest, Last] ? Last : never
type L = Last<Arr>
模版字符串
type A = 'A'
type B = 'B'
type C = 'C'
type X = `${A} ${B} ${C}` // TODO: 'A B C'
没错,模版字符串在 TS 中也能使用
怎么获取字符串的第一个?没错还是用模式匹配
type A = 'ji ni tai mei'
type First<T extends string> = T extends `${inter First}${string}` ? F : never
type Result = First<A> // TODO: j
那怎么获取字符串的最后一项呢?似乎有点麻烦,也许可能用递归能实现
但是这个时候就需要换一种思路了,获取元组的最后一项非常简单,那么直到能把字符串转换成元组就好了(体操最重要的就是思路!)
type A = 'ji ni tai mei'
type LastOfArr<T extends unknown[]> = T extends [...inter _, inter Last] ? Last : never
type StringToArr<T extends string> = T extends `${inter F}${inter Rest}` ? [F, ...StringToArr<Rest>] : []
type LastOfString = LastOfArr<StringToArr<A>>
相应的也能转换成联合类型
type A = 'ji ni tai mei'
type StringToUnion<T extends string> = T extends `${inter F}${inter Rest}` ? F | StringToUnion<Rest> : never
type Result = StringToUnion<A> // TODO: 'j' | 'i' | 'n' | 't' | 'a' | 'm' | 'e'
// TODO: 注意,联合类型自动去重了