• TypeScript详解十四:自定义工具类型



    前言

    在日常工作中,有时为了满足特殊的需求,需要定制一些自定义工具类型,以达到提高工作效率及简化代码的目的。本篇文章将记录几种自定义工具类型的使用及实现,以便学习。
    更多自定义工具可以参考 utility-types


    提示:以下是本篇文章正文内容,下面案例可供参考

    1.Proxy

    • 代理:将对象变为响应式
    namespace a {
      type Proxy<T> = {
        get(): T,
        set(value: T): void
      }
    
      type Proxity<T> = {
        [P in keyof T]: Proxy<T[P]>;
      }
    
      function proxity<T>(obj: T): Proxity<T> {
        let result = <Proxity<T>>{};
        for (const key in obj) {
          Object.defineProperty(result, key, {
            enumerable: true,
            configurable: true,
            get: () => {
              return obj[key];
            },
            set: (value) => {
              obj[key] = value;
            }
          })
        }
        return result;
      }
      interface Props {
        name: string,
        age: number
      }
      let obj: Props = {
        name: '张三',
        age: 10
      }
      obj.name = '李四'
      let res = proxity<Props>(obj);
      console.log(res); // { name: [Getter/Setter], age: [Getter/Setter] }
    }
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.unProxy

    • 取消代理
    namespace a {
      type Proxy<T> = {
        get(): T,
        set(value: T): void
      }
    
      type Proxity<T> = {
        [P in keyof T]: Proxy<T[P]>;
      }
      
      function unProxity<T>(t: Proxity<T>): T {
        let result: any = {} as T;
        for (const key in t) {
          result[key] = t[key];
        }
        return result;
      }
    
      let ret = unProxity<Props>(res);
      console.log(ret); // { name: '李四', age: 10 }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.SetDifference

    • 差集
    • 返回 T 中有,U中没有的属性,和 Exclude 一致
    namespace b {
      type SetDifference<T, U> = T extends U ? never : T;
      type A = string | number | symbol;
      type B = number | boolean;
      type AB = SetDifference<A, B>; // type AB = string | symbol
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.Omit

    • 忽略
    • 忽略某些属性,返回剩余的属性
    • keyof T 是name | age | isMan
    • K 是传递进来的 ‘age’ | ‘name’
    • SetDifference就相当于从 name | age | isMan中找出不含 age | name的属性
    • 通过 Pick 返回筛选后的属性,即 { isMan: boolean; }
    namespace c {
      type SetDifference<T, U> = T extends U ? never : T;
      type Omit<T, K extends keyof any> = Pick<T, SetDifference<keyof T, K>>;
      type Person = { name: string, age: number, isMan: boolean };
      type OmitAgePerson = Omit<Person, 'age' | 'name'>; // { isMan: boolean; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.Diff

    • 差集
    • 返回 T 中有,U中没有的属性
    • 和 SetDifference、Exclude 基本一致
    namespace d {
      type Props = { name: string, age: number, isMan: boolean };
      type DefaultProps = { age: number };
      type SetDifference<T, U> = T extends U ? never : T;
      type Diff<T extends object, U extends object> = Pick<T, SetDifference<keyof T, keyof U>>;
      type DiffProps = Diff<Props, DefaultProps>; // { name: string, isMan: boolean; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    6.InterSection

    • 交集
    • 返回 T 和 U 中共有的属性
    namespace e {
      // 注意:下面这三种写法都可以
      // Extract & Extract
      // Extract
      // Extract
      type InterSection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>>;
      type Props = { name: string, age: number, isMan: boolean };
      type DefaultProps = { age: number };
      type DuplicateProps = InterSection<Props, DefaultProps>; // { age: number }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.OverWrite

    • 重写
    • 返回 T 和 U 中都有的属性,并且用 U 中的属性覆盖 T 中的属性
    namespace f {
      type OldProps = { name: string, age: number, isMan: boolean };
      type NewProps = { name: number, sex: string };
      // SetDifference 找出 T 中有,但 U 中没有的属性
      type SetDifference<T, U> = T extends U ? never : T;
      // Diff 找出 T 中有,但 U 中没有的属性
      type Diff<T extends object, U extends object> = Pick<T, SetDifference<keyof T, keyof U>>;
      // InterSection 找出 T 和 U 中都有的属性
      type InterSection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>>;
      type OverWrite<
        T extends object,
        U extends object,
        // Diff 是:{ age: number, isMan: boolean }
        // InterSection 是:{ name:number }
        // 所以 I 就是:{ name:number, age: number, isMan: boolean }
        // 如果也想返回 sex 属性,那么此处需要改写成 I = Diff & U
        I = Diff<T, U> & InterSection<U, T>
      > = Pick<I, keyof I>;
      type ReplaceProps = OverWrite<OldProps, NewProps>; // { name: number, age: number, isMan: boolean };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    8.Merge

    • 合并
    • 将两个对象合并为一个对象
    namespace g {
      type Obj1 = {
        id: number,
        name: string
      }
      type Obj2 = {
        id: number,
        age: number
      }
      type Compute<T extends any> = T extends Function ? T : { [K in keyof T]: T[K] };
      type SetDifference<T, U> = T extends U ? never : T;
      type Omit<T, K extends keyof any> = Pick<T, SetDifference<keyof T, K>>;
      type Merge<T extends object, U extends object> = Compute<Obj1 & Omit<Obj2, keyof Obj1>>;
      type obj = Merge<Obj1, Obj2>;
      /**
        type obj = {
          id: number;
          name: string;
          age: number;
        }
       */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    总结

    本篇文章主要记录了ts中的一些自定义工具类型,下次再见。

  • 相关阅读:
    VB.NET vs. VB6.0:现代化编程语言 VS 经典老旧语言
    Springcloud----Nacos配置中心
    HOOPS/QT集成指南
    性能指标都不了解,如何做性能测试?
    第十三届蓝桥杯C++B组国赛I题——齿轮 (AC)
    决策树,sql考题,30个经典sql题目
    买卖股票的最佳时机 II
    C语言部分复习笔记
    运行结果和预期结果不一样
    百度:文心大模型日均处理Tokens文本已达2490亿
  • 原文地址:https://blog.csdn.net/to_the_Future/article/details/126920675