1、LengthOfTuple

计算元组类型的长度

  1. type A = LengthOfTuple<['B', 'F', 'E']> // 3
  2. type B = LengthOfTuple<[]> // 0

实现:

  1. type LengthOfTuple<T extends any[]> = T extends { length: infer L } ? L : never

2、FirstItem

得到元组类型中的第一个元素

  1. type A = FirstItem<[string, number, boolean]> // string
  2. type B = FirstItem<['B', 'F', 'E']> // 'B'
  3. type C = FirstItem<[]> // never

实现:

  1. type FirstItem<T extends any[]> = T extends [infer First, ...infer Rest] ? First : never

3、LastItem

得到元组类型中的最后一个元素

  1. type A = LastItem<[string, number, boolean]> // boolean
  2. type B = LastItem<['B', 'F', 'E']> // 'E'
  3. type C = LastItem<[]> // never

实现:

  1. type LastItem<T extends any[]> = T extends [...infer Rest, infer Last] ? Last : never

4、Shift

移除元组类型中的第一个类型

  1. type A = Shift<[1, 2, 3]> // [2,3]
  2. type B = Shift<[1]> // []
  3. type C = Shift<[]> // []

实现:

  1. type Shift<T extends any[]> = T extends [infer First, ...infer Rest] ? Rest : T

5、Push

在元组类型T中添加新的类型I

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

实现:

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

6、ReverseTuple

反转元组

  1. type A = ReverseTuple<[string, number, boolean]> // [boolean, number, string]
  2. type B = ReverseTuple<[1, 2, 3]> // [3,2,1]
  3. type C = ReverseTuple<[]> // []

实现:

  1. type ReverseTuple<T extends any[], Prev extends any[] = []> = T extends [...infer Rest, infer Last] ? ReverseTuple<Rest, [...Prev, Last]> : Prev

7、Flat

拍平元组

  1. type A = Flat<[1, 2, 3]> // [1,2,3]
  2. type B = Flat<[1, [2, 3], [4, [5, [6]]]]> // [1,2,3,4,5,6]
  3. type C = Flat<[]> // []
  4. type D = Flat<[1]> // [1]

实现:

  1. type Flat<T extends any[], Prev extends any[] = []> = T extends [infer First, ...infer Rest] ? (
  2. First extends any[] ? Flat<Rest, Flat<First, Prev>> : Flat<Rest, [...Prev, First]>
  3. ) : Prev

8、Repeat

复制类型T为C个元素的元组类型

  1. type A = Repeat<number, 3> // [number, number, number]
  2. type B = Repeat<string, 2> // [string, string]
  3. type C = Repeat<1, 1> // [1]
  4. type D = Repeat<0, 0> // []

实现:

  1. type Repeat<T, C extends number, Prev extends any[] = []> = Prev['length'] extends C ? Prev : Repeat<T, C, [...Prev, T]>

9、Filter

保留元组类型T中的A类型

  1. type TypeEquals<T, S> = [T] extends [S] ? true : false
  2. type Filter<T extends any[], A, Prev extends any[] = []> = T extends [infer First, ...infer Rest] ? (
  3. TypeEquals<First, A> extends true ? Filter<Rest, A, [...Prev, First]> : Filter<Rest, A, Prev>
  4. ) : Prev

TypeScript中的Equal的玩法:https://github.com/microsoft/TypeScript/issues/27024

10、FindIndex

找出E类型在元组类型T中的下标

  1. type A = [any, never, 1, '2', true]
  2. type B = FindIndex<A, 1> // 2
  3. type C = FindIndex<A, 3> // never

实现:

  1. type Equals<X, Y> =
  2. (<T>() => T extends X ? 1 : 2) extends
  3. (<U>() => U extends Y ? 1 : 2) ? true : false
  4. type FindIndex<T extends any[], E, Prev extends any[] = []> = T extends [infer First, ...infer Rest] ? (
  5. Equals<First, E> extends true ? Prev['length'] : FindIndex<Rest, E, [...Prev, First]>
  6. ) : never

小结:
在9、10题中,选择了不同的Equals判断类型,是由类型判断的严格程度决定的。

11、TupleToEnum

元组类型转换为枚举类型

  1. // 默认情况下,枚举对象中的值就是元素中某个类型的字面量类型
  2. type a1 = TupleToEnum<["MacOS", "Windows", "Linux"]>
  3. // -> { readonly MacOS: "MacOS", readonly Windows: "Windows", readonly Linux: "Linux" }
  4. // 如果传递了第二个参数为true,则枚举对象中值的类型就是元素类型中某个元素在元组中的index索引,也就是数字字面量类型
  5. type a2 = TupleToEnum<["MacOS", "Windows", "Linux"], true>
  6. // -> { readonly MacOS: 0, readonly Windows: 1, readonly Linux: 2 }

实现:

  1. type Equals<X, Y> =
  2. (<T>() => T extends X ? 1 : 2) extends
  3. (<U>() => U extends Y ? 1 : 2) ? true : false
  4. type FindIndex<T extends any[], E, Prev extends any[] = []> = T extends [infer First, ...infer Rest] ? (
  5. Equals<First, E> extends true ? Prev['length'] : FindIndex<Rest, E, [...Prev, First]>
  6. ) : never
  7. type TupleToEnum<T extends string[], V extends boolean = false> = {
  8. readonly [K in T[number]]: V extends true ? FindIndex<T, K> : K
  9. }

12、Slice

截取元组中的部分元素

  1. type A1 = Slice<[any, never, 1, '2', true, boolean], 0, 2> // [any,never,1] 从第0个位置开始,保留到第2个位置的元素类型
  2. type A2 = Slice<[any, never, 1, '2', true, boolean], 1, 3> // [never,1,'2'] 从第1个位置开始,保留到第3个位置的元素类型
  3. type A3 = Slice<[any, never, 1, '2', true, boolean], 1, 2> // [never,1] 从第1个位置开始,保留到第2个位置的元素类型
  4. type A4 = Slice<[any, never, 1, '2', true, boolean], 2> // [1,'2',true,boolean] 从第2个位置开始,保留后面所有元素类型
  5. type A5 = Slice<[any], 2> // [] 从第2个位置开始,保留后面所有元素类型
  6. type A6 = Slice<[], 0> // [] 从第0个位置开始,保留后面所有元素类型

实现:

  1. type TupleSplit<T extends any[], N extends number, O extends any[] = []> =
  2. O['length'] extends N ? [O, T] : T extends [infer First, ...infer Rest] ?
  3. TupleSplit<Rest, N, [...O, First]> : [O, T]
  4. type TakeFirst<T extends any[], N extends number> = TupleSplit<T, N>[0]
  5. type SkipFirst<T extends any[], N extends number> = TupleSplit<T, N>[1]
  6. type Slice<T extends any[], Start extends number, End extends number = 0> =
  7. End extends 0 ? SkipFirst<TakeFirst<T, T['length']>, Start> :
  8. SkipFirst<[...TakeFirst<T, End>, ...TakeFirst<SkipFirst<T, End>, 1>], Start>

13、Splice

删除并且替换部分元素

  1. type A1 = Splice<[string, number, boolean, null, undefined, never], 0, 2> // [boolean,null,undefined,never] 从第0开始删除,删除2个元素
  2. type A2 = Splice<[string, number, boolean, null, undefined, never], 1, 3> // [string,undefined,never] 从第1开始删除,删除3个元素
  3. type A3 = Splice<[string, number, boolean, null, undefined, never], 1, 2, [1, 2, 3]> // [string,1,2,3,null,undefined,never] 从第1开始删除,删除2个元素,替换为另外三个元素1,2,3

实现:

  1. type TupleSplit<T extends any[], N extends number, O extends any[] = []> =
  2. O['length'] extends N ? [O, T] : T extends [infer First, ...infer Rest] ?
  3. TupleSplit<Rest, N, [...O, First]> : [O, T]
  4. type TakeFirst<T extends any[], N extends number> = TupleSplit<T, N>[0]
  5. type SkipFirst<T extends any[], N extends number> = TupleSplit<T, N>[1]
  6. type Splice<T extends any[], S extends number, E extends number, A extends any[] = []> =
  7. A extends [] ? [...TakeFirst<T, S>, ...SkipFirst<SkipFirst<T, S>, E>] : [...TakeFirst<T, S>, ...A, ...SkipFirst<SkipFirst<T, S>, E>]