0%

类型体操训练

Tuple

1
2
3
4
5
6
7
type A = Tuple<1> // [void]
type B = Tuple<2> // [void,void]
type C = Tuple<3> // [void,void,void]

type Tuple<T extends number, U extends void[] = []> = U['length'] extends T
? U
: Tuple<T, [void, ...U]>

TupleO2N

1
2
3
4
5
6
7
type A = Tuple2N<1> // [0]
type B = Tuple2N<2> // [0, 1]
type C = Tuple2N<3> // [0, 1, 2]

type TupleO2N<T extends number, U extends number[] = []> = U['length'] extends T
? U
: TupleO2N<T, [...U, U['length']]>

Tuple2N

1
2
3
4
5
6
7
8
9
type A = Tuple2N<1> // [1]
type B = Tuple2N<2> // [1,2]
type C = Tuple2N<3> // [1,2,3]

type Tuple2N<T extends number, U extends number[] = []> = U['length'] extends T
? U extends [0, ...infer R]
? [...R, T]
: never
: Tuple2N<T, [...U, U['length']]>

TupleM2N

1
2
3
4
5
6
7
8
9
type A = TupleM2N<1, 1> // [1]
type B = TupleM2N<2, 2> // [2,3]
type C = TupleM2N<3, 9> // [9,10,11]

type TupleM2N<
M extends number,
N extends number,
L extends any[] = [...TupleO2N<M>, ...TupleO2N<N>]
> = TupleO2N<L['length']> extends [...TupleO2N<N>, ...infer R] ? R : never

Subtract

1
2
3
4
5
type A = Subtract<3,3> // 0
type B = Subtract<10,7> // 3

type Subtract<M extends number, N extends number > =
Tuple<M> extends [...Tuple<N>, ... infer R] ? R['length'] : never

Add

1
2
3
4
5
6
7
8
type A = Add<3, 3> // 6
type B = Add<10, 7> // 17

type Add<
M extends number,
N extends number,
R extends any[] = [...Tuple<M>, ...Tuple<N>]
> = R['length']

String2Number

1
2
3
4
5
6
7
8
9
type A = String2Number<'3'> // 3
type B = String2Number<'10'> // 10

type String2Number<
A extends string,
B extends number[] = []
> = `${B['length']}` extends A
? B['length']
: String2Number<A, [...B, B['length']]>

Negative2Positive

1
2
3
4
5
6
type A = Negative2Positive<-1> // 1
type B = Negative2Positive<-10> // 10

type Negative2Positive<N extends number> = `${N}` extends `-${infer R}`
? String2Number<R>
: N

Divide

1
2
3
4
5
6
7
8
9
10
11
12
13
type A = Divide<10, 3> // 3
type B = Divide<10, 2> // 5
type C = Divide<10, 0> // never

type Divide<
N extends number,
M extends number,
R extends any[] = [],
> = M extends 0
? never
: Tuple<N> extends [...Tuple<M>, ...infer F]
? Divide<F['length'], M, [any, ...R]>
: R['length'];

Multiply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type A = Multiply<3, 3> // 9
type B = Multiply<10, 2> // 20
type C = Multiply<10, 0> // 0

type Multiply<
N extends number,
M extends number,
R extends void[] = [void],
F extends any[] = Tuple<M>
> = N extends 0
? 0
: M extends 0
? 0
: R['length'] extends N
? F['length']
: Multiply<N, M, [void, ...R], [...F, ...Tuple<M>]>

Pow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type A = Pow<3, 3> // 27
type B = Pow<10, 2> // 100
type C = Pow<10, 0> // 1
type D = Pow<10, 1> // 10


type Number<A extends any> =
A extends A
? A
: A
type Pow<N extends number, M extends number, R extends void[] = [void], F extends number = N> =
N extends 0
? 0
: M extends 0
? 1
: R['length'] extends M
? F
: Pow<N, M, [void, ...R], Number<Multiply<F,N>>>

Push

1
2
3
type A = Push<[1, 2, 3], 4> // [1,2,3,4]

type Push<T extends any[], I> = [...T, I]

Pop

1
2
3
type A = Pop<[1, 2, 3, 4]> // [1,2,3]

type Pop<T extends any[], R = T extends [...infer R, any] ? R : []> = R

UnShift

1
2
3
type A = UnShift<[2,3,4], 1> // [1,2,3,4]

type UnShift<T extends any[], I> = [I, ...T];

Shift

1
2
3
type A = Shift<[1,2,3,4]> // [2,3,4]

type Shift<T extends any[]> = T extends [any, ...infer R] ? R : T;

Concat

1
2
3
type A = Concat<[1,2], [3,4]> // [1,2,3,4]

type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U];

ConcatAdv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type A = ConcatAdv<[1], [2], [3], [4], []>; // [1,2,3,4]

type ConcatAdv<
T1 extends any[] = [],
T2 extends any[] = [],
T3 extends any[] = [],
T4 extends any[] = [],
T5 extends any[] = [],
T6 extends any[] = [],
T7 extends any[] = [],
T8 extends any[] = [],
T9 extends any[] = [],
T10 extends any[] = [],
T11 extends any[] = [],
> = [
...T1,
...T2,
...T3,
...T4,
...T5,
...T6,
...T7,
...T8,
...T9,
...T10,
...T11,
];

Join

1
2
3
4
5
6
7
type A = Join<[1,2,3], ','> // '1,2,3,4'

type Join<T extends any[], S extends string = ''> = T extends [any, ...infer R]
? R extends []
? `${T[0]}`
: `${T[0]}${S}${Join<R, S>}`
: '';