• TypeScript 类型体操


    1. Pick

    type MyPick<T, U extends keyof T> = {
        [P in U]: T[P]
    }
    
    • 1
    • 2
    • 3

    2. Readonly

    type MyReadonly<T> = {
        readonly [P in keyof T]: T[P]
    }
    
    • 1
    • 2
    • 3

    3. Tuple to Object

    type TupleToObject<T extends ReadonlyArray<string | number>> = {
      [P in T[number]]: P
    }
    
    • 1
    • 2
    • 3

    4. First

    取数组的第一个元素

    type First<T extends unknown[]> = T extends [infer P, ...unknown[]] ? P : never
    
    • 1

    5. Array length

    取数组的长度

    type Length<T extends ReadonlyArray<unknown>> = T['length']
    
    • 1

    6. Exclude

    type MyExclude<T, U> = T extends U ? never : T
    
    • 1

    7. Awaited

    假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。

    比如:Promise<ExampleType>,请返回 ExampleType 类型。

    type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer P>
    												? (P extends Promise<unknown> ? MyAwaited<P> : P) 
    												: never
    
    • 1
    • 2
    • 3

    先用条件推断,泛型T是否是Promise返回,并用infer P指代返回值。
    P有两种情况:

    1. 普通返回值类型
    2. Promise类型

    如果P是Promise类型,则需要递归检查。对应的代码是:
    P extends Promise<unknown> ? MyAwaited<P> : P

    如果是普通返回值类型,则直接返回P
    为什么要加extends Promise<unknown>?
    MyAwaited<T extends Promise<unknown>>的含义,是为了避免用户传入非Promise function
    如果用户违反规则,TypeScript会按报错处理。

    8. If

    type If<C extends boolean, T, F> = C extends true ? T : F
    
    • 1

    9. Concat

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

    10. Includes


    type Equal<X, Y> =
        (<T>() => T extends X ? 1 : 2) extends
            (<T>() => T extends Y ? 1 : 2) ? true : false
    
    • 1
    • 2
    • 3

    // 逐个递归取出 Equal 比较
    type Includes<T extends ReadonlyArray<any>, U> = T extends [infer R, ... infer K]
    													? (Equal<U, R> extends true ? true : Includes<K, U>)
    													: false
    
    • 1
    • 2
    • 3
    • 4
    // 循环比较
    type Includes<T extends ReadonlyArray<any>, U> = {
      [K in keyof T]: Equal<U, T[K]>
    }[number] extends false ? false : true
    
    • 1
    • 2
    • 3
    • 4

    11. Push

    type Push<T extends unknown[], U> = [...T, U]
    
    • 1

    12. Unshift

    type Unshift<T extends unknown[], U> = [U, ...T]
    
    • 1

    13. Parameters

    ts内置Parameters 获取函数参数 转为 元组

    type MyParameters<T extends (...args: any[]) => any> = T extends ((...args: infer P) => any) ? P : never
    
    • 1

    14. ReturnType

    ts内置ReturnType 获取函数返回值类型

    type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer P ? P : never
    
    • 1

    15. Omit

    ts内置Omit

    type MyOmit<T, K extends keyof T> = {
      [P in Exclude<keyof T, K>]: T[P]
    }
    
    • 1
    • 2
    • 3

    使用Exclude排除keyof T中的K类型

    16. Readonly 2

    实现一个通用MyReadonly2<T, K>,它带有两种类型的参数TK
    K指定应设置为ReadonlyT的属性集。如果未提供K,则应使所有属性都变为只读,就像普通的Readonly<T>一样

    type MyReadonly2<T, K extends keyof T = keyof T> = {
      readonly [P in K]: T[P]
    } & Omit<T, K>
    
    • 1
    • 2
    • 3

    17. DeepReadonly

    实现一个通用的DeepReadonly<T>,它将对象的每个参数及其子对象递归地设为只读。

    type DeepReadonly<T> = {
      readonly [P in keyof T]: T[P] extends Function ? T[P] : (T[P] extends {} ? DeepReadonly<T[P]> : T[P])
    }
    
    • 1
    • 2
    • 3

    From vue3 完美实现

    type Primitive = string | number | boolean | bigint | symbol | undefined | null
    type Builtin = Primitive | Function | Date | Error | RegExp
    type DeepReadonly<T> = T extends Builtin
      ? T
      : T extends Map<infer K, infer V>
        ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
        : T extends ReadonlyMap<infer K, infer V>
          ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
          : T extends WeakMap<infer K, infer V>
            ? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
            : T extends Set<infer U>
              ? ReadonlySet<DeepReadonly<U>>
              : T extends ReadonlySet<infer U>
                ? ReadonlySet<DeepReadonly<U>>
                : T extends WeakSet<infer U>
                  ? WeakSet<DeepReadonly<U>>
                  : T extends Promise<infer U>
                    ? Promise<DeepReadonly<U>>
                    : T extends {}
                      ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
                      : Readonly<T>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    18. Tuple to Union

    type TupleToUnion<T extends ReadonlyArray<unknown>> = T[number]
    
    • 1
  • 相关阅读:
    【C#】xml解析对比XDocument和XmlDocument
    寻找小红书达人技巧有哪些,小红书行业黑话汇总!
    论坛介绍 | COSCon'23 云计算(C)
    A股风格因子看板 (2023.10 第11期)
    什么是Ribbon,怎么实现负载均衡?
    谷粒商城-商品服务(分类、品牌管理)
    vue 概述
    NFT 交易市场的后起之秀要如何超越 OpenSea?
    服务器部署 CentOS、VeraCrypt、Docker、主从MySQL、Redis、备份等
    家庭安全计划 挑战赛| 溺水预防
  • 原文地址:https://blog.csdn.net/weixin_41496591/article/details/125509828