体操就是做锻炼,给你的大脑做锻炼
有没有什么实际的意义呢?我觉得没有,工作中用不到,只是为了锻炼而已

if else

JS:

1
2
3
4
5
if (A <= B) {
return true
} else {
return false
}

TS:

1
2
3
type A = 1
type B = 1 | 2
type Result = A extends B ? true : false

加一点复杂

JS:

1
2
3
4
5
if (A<= B && C<= D) {
...
} else {
...
}

TS:

1
2
3
4
5
6
7
8
9
10
11
12
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 类型体操的蛋疼之处,并不是逻辑复杂,而是看起来复杂

判断是否是元组

1
2
3
4
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr['length'] extends 0 ? true : false

type Result = IsEmptyArray<A> // TODO: true

infer

还是以上面判断是否为元组的栗子:

1
2
3
4
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr extends [...inter X[], inter D] ? true : false

type Result = IsEmptyArray<A> // TODO: true

这里用 inter “引用”(可以把它当做 var),等价于:

1
2
3
4
type A = []
type IsEmptyArray<T exxtends unknown[]> = Arr extends [...unknown[], unknown] ? true : false

type Result = IsEmptyArray<A> // TODO: true

递归

等价于 for 循环,但是在 TS 中递归有层数限制(不多),有兴趣动手可以测试一下

1
2
3
4
5
6
7
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']

模式匹配

合并元组

1
2
3
4
type A = [1, 2]
type B = [3, string]

type C = [...A, ...B]

获取元组的最后一项

1
2
3
4
type Arr = [1, 2, 3, 4]
type Last<T extends unknown[]> = T extends [...Rest, Last] ? Last : never

type L = Last<Arr>

模版字符串

1
2
3
4
5
type A = 'A'
type B = 'B'
type C = 'C'

type X = `${A} ${B} ${C}` // TODO: 'A B C'

没错,模版字符串在 TS 中也能使用

怎么获取字符串的第一个?没错还是用模式匹配

1
2
3
4
5
type A = 'ji ni tai mei'

type First<T extends string> = T extends `${inter First}${string}` ? F : never

type Result = First<A> // TODO: j

那怎么获取字符串的最后一项呢?似乎有点麻烦,也许可能用递归能实现

但是这个时候就需要换一种思路了,获取元组的最后一项非常简单,那么直到能把字符串转换成元组就好了(体操最重要的就是思路!)

1
2
3
4
5
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>>
相应的也能转换成联合类型
1
2
3
4
5
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: 注意,联合类型自动去重了