TS之体操

82 阅读2分钟

infer

  • TypeScript文档:Here, we used the infer keyword to declaratively introduce a new generic type variable named Item instead of specifying how to retrieve the element type of T within the true branch. This frees us from having to think about how to dig through and probing apart the structure of the types we’re interested in.

  • type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;

  • extends的条件语句中推导泛型参数
    // 推断函数的返回值类型
    type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never
    
    type func = () => numbers
    type Variable  = string
    
    type funcReturnType = ReturnType<func> // number
    type VariableReturnType = ReturnType<Variable> // never
    

infer解包

// 获取数组的类型
type GetArrayType<T> = T extends Array<infer R> ? R : never;
type Result = GetArrayType<[2, "3"]>; // 2 | "3"

使用递归

  • 反转元组
type Reverse<Arr extends unknown[]> = 
    Arr extends [...infer First, infer Laster] 
        ? [Laster, ...Reverse<First>] : Arr
type N = [1, 2, 3, 4, 5];
type Result = Reverse<N>; // [5, 4, 3, 2, 1]

基本体操

extends

  • 使用extends进行条件判断
  1. 判断是否为空数组
    type IsEmptyArray<T extends unknown[]> = 
       T["length"] extends 0 ? true : false
    

递归

  • 使用递归反转数组
    type Reverse<T extends unknown[]> = T extends [...infer Arr, infer Last]
      ? [Last, ...Reverse<Arr>]
      : T;
    

元组

  • ...
    type A = [1]
    type B = [2]
    type Result = [...A, ...B]
    
  • 获取最后一个元素类型
    type Last<T extends unknown[]> = 
        T extends [...infet F, infer L] ? L : never
    // 获取除最后一元素的类型
    type NotLast<T extends unknown[]> = 
        T extends [...infet F, infer L] ? F : never
    

字符串

  • TS内置泛型

    1. Uppercase 全部大写
    2. Lowercase 全部小写
    3. Capitalize 首字母大写
    4. Uncapitalize 首字母小写
  • 获取第一个类型

    type First<T extends string> = 
        T extends `${infer F}${string}` ? F : never
    
  • 将string类型变为联合类型

    • 联合类型自动去重
    type  StringToUnion<T extends string> = 
        T extends `${infer F}${infer R}` 
            ? F | StringToUnion<R> : never
    type A = '12310';
    type Result = StringToUnion<A>;
     // type Result = '1' | '2' | '3' | '0'
    
  • 将string变为元组

type StringToTuple<T extends string> = 
    T extends `${infer F}${infer R}` ?
        [F, ...StringToTuple<R>] : []

体操练习

  1. Pick
    type MyPick<T, K extends keyof T> = {
        [P in K]: K[P] 
    }    
    
  2. Parameters
    type MyParameters<T extends (args:...any[]) => any> = 
        T extends (args: ...infer A) => any ? A : never
    
  3. Awaited
    • 获取Promise的返回的类型
    type MyAwaited<T extends Promise<any>> = T extends Promise<infer K>
      ? K extends Promise<any>
        ? MyAwaited<K>
        : K
      : never;
    
  4. Zip
    • 将两个元组按下标合并为一个元组,
type Zip<A extends unknown[], B extends unknown[]> = 
    A extends [ infer AFirst, ...infer ARest ]
      ? B extends [infer BFirst, ...infer BRest]
        ? [[AFirst, BFirst], ...Zip<ARest, BRest>]
        : []
      : [];
ty
type exp = Zip<[1, 2, 3], [true, false]>;
// type exp = [[1, true], [2, false]]
  1. isTuple
    • 返回泛型T是否为元组类型
type IsTuple<T> = T extends readonly any[]
  ? number extends T["length"]
    ? false
    : true
  : T extends { length: number }
  ? false
  : true;
type IsTupleResult1 = IsTuple<string[]>; // false
type IsTupleResult2 = IsTuple<[string]>; // true
  1. Join
  • 实现Array.join的类型版本,拼接元组和字符
type Join<T extends string[], U extends string | number> = T extends [
  infer First extends string,
  ...infer Rest extends string[]
]
  ? Rest["length"] extends 0
    ? First
    : `${First}${U}${Join<Rest, U>}`
  : "";

type JoinResult = Join<["1", "2", "23", "3"], "#"> // "1#2#23#3"
type JoinResult1 = Join<["1"], "#"> // "1"