TS数组类型体操

25 阅读1分钟

1、取第一个值

// 取第一个值
type FirstItem<T extends any[]> = T[0]

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

2、取最后一个值

// 取最后一个值
type LastItem<T extends any[]> = T extends [...any, infer L] ? L : never

// 3
type D = LastItem<[1, 2, 3]>
// boolean
type E = LastItem<[string, number, boolean]>
// never
type F = LastItem<[]>

3、Shift

// 将第一个元素剔除,取剩余元素 Shift
type Shift<T extends any[]> = T extends [infer F, ...infer L] ? L : never

// [2, 3]
type G = Shift<[1, 2, 3]>
// []
type H = Shift<[string]>
// never
type I = Shift<[]>

4、Push

// 在尾部添加元素,Push
type Push<T extends any[], E> = [...T, E]

// [1, 2, 3, 4]
type A1 = Push<[1, 2, 3], 4>
// [string, number]
type B1 = Push<[string], number>
// [boolean]
type C1 = Push<[], boolean>

5、数组反转

type Reverse<T extends any[], R extends any[] = []> = T extends [infer F, ...infer L] ?
Reverse<L, [F, ...R]> : R

// [3, 2, 1]
type A2 = Reverse<[1, 2, 3]>
// [number, string]
type B2 = Reverse<[string, number]>
// []
type C2 = Reverse<[]>

6、数组扁平化

type Flatten<T extends any[]> = T extends [infer F, ...infer L] ?
  [...(F extends any[] ? Flatten<F> : [F]), ...Flatten<L>] : 
  []

// [1, 2, 3, 4, 5, 6]
type A3 = Flatten<[1, 2, [3, 4, [5, 6]]]>
type B3 = Flatten<[]>

7、重复值组成数组

// 重复值组成数组
type Repeat<T, N extends number, R extends any[] = []> = R['length'] extends N ? 
    R : 
    Repeat<T, N, [T, ...R]>

// [1, 1, 1, 1, 1]
type A4 = Repeat<1, 5>

8、筛选出数组中的某些值

// 过滤元素,返回新数组 Filter
// 第一参数是数组,第二参数是要筛选的值
type Filter<T extends any[], Target, R extends any[] = []> = T extends [infer F, ...infer L] ?
    Filter<L, Target, ([F] extends [Target] ? [...R, F] : R)> :
    R

// 注意any会出发分发机制,使用[]避免
// [1, 3, any]
type A5 = Filter<[1, '2', 3, any, '5'], number>

9、查找元素,返回索引

// 判断是否相等,类型,结构都得判断,防止any
type isEqual<T, U, S, F> = [T] extends [U] ?
    [U] extends [T] ? 
        keyof T extends keyof U ? 
            keyof U extends keyof T ? 
                S :
                F : 
            F : 
        F :
    F 

// 用数组的length返回数值
type FindIndex<T extends any[], Target, R extends any[] = []> = T extends [infer F, ...infer L] ?
    isEqual<F, Target, R['length'],  FindIndex<L, Target, [...R, F]>> :
    never

// 4  
type A6 = FindIndex<[1, '2', 3, any, '5'], '5'>

10、元组转枚举

// 第一参数是元组,第二参数 false: 取值,true: 取索引
type TupleToEnum<T extends any[],  R = false> = {
    [key in T[number]]: isEqual<R, false, key, FindIndex<T, key>>
}

// {
//     a: "a";
//     b: "b";
//     c: "c";
// }
type A7 = TupleToEnum<['a', 'b', 'c']>
// {
//     a: 0;
//     b: 1;
//     c: 2;
// }
type B7 = TupleToEnum<['a', 'b', 'c'], true>