[月分享] TypeScript - 常用内置类型与使用技巧

简介: [月分享] TypeScript - 常用内置类型与使用技巧


/**
 * keyof<T>
 *  获取一个对象接口的所有 key 值
 *  keyof 与 Object.keys 略有相似,只不过 keyof 取 interface 的键。
 */
() => {
  interface Person {
    name: string;
    age: number;
    location: string;
  }

  type K1 = keyof Person; // "name" | "age" | "location"
  type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ...
  type K3 = keyof { [x: string]: Person }; // string

  // 获取对象的属性
  function pluck<T, K extends keyof T>(o: T, names: K): T[K] {
    return o[names];
  }
};
(_tip: "keyof 只会返回不为 null undefined never 的类型") => {
  interface EnumType {
    a: never;
    b: undefined;
    c: null;
    d: number;
    e: object;
  }
  type TypeEnumType = keyof EnumType; // a | b | c | d | e
  type TypeEnumType1 = EnumType[keyof EnumType]; // number | object 去除了了3种假类型

  type ReadonlyType<T> = {
    readonly [P in keyof T]?: T[P];
  };
  let readOnly: ReadonlyType<EnumType> = {}; // 将 EnumType 所有类型都变为了了 只读
};

/**
 * Pick<T, K>
 *  从对象类型 T 挑选一些属性 K
 *  比如对象拥有 5 个 key,只需要将 K 设置为 "name" | "age" 就可以生成仅支持这两个 key 的新对象类型。
 */
() => {
  interface IObj {
    a: string;
    b: number;
    c: boolean;
  }
  type FilterObj = Pick<IObj, "a" | "b">;
  const test: FilterObj = {
    a: "str",
    b: 1,
  };
};

/**
 * Extract<T, U>
 *  挑选 key 中的 key
 *  Extract 是 Pick 的底层 API,直到 2.8 版本才内置进来,
 *  可以认为 Pick 是挑选对象的某些 key,Extract 是挑选 key 中的 key。
 */
() => {
  interface IObj {
    a: string;
    b: number;
    c: boolean;
  }
  type FilterKey = Extract<keyof IObj, "a">;
  const test: FilterKey = "a";
};

/**
 * Exclude<T, U>
 *  将 T 中的 U 类型排除,和 Extract 功能相反。
 */
() => {
  interface IObj {
    a: string;
    b: number;
    c: boolean;
  }
  type FilterKey = Exclude<keyof IObj, "a" | "b">;
  const test: FilterKey = "c";
};

/**
 * Record<K, U>
 *  将 K 中所有的属性的值转化为 U 类型
 *  ts文档上对Record的介绍不多,但却经常用到,Record是一个很好用的工具类型。
 *  他会将一个类型的所有属性值都映射到另一个类型上并创造一个新的类型
 */
(_tip: "源码") => {
  // 将K中的所有属性值都转换为T类型,并将返回的新类型返回给proxyKType,K可以是联合类型、对象、枚举
  type Record<K extends keyof any, T> = {
    [P in K]: T;
  };
};
(_tip: "Demo") => {
  interface AnimalsInfo {
    dog: {
      name: string;
      age: number;
    };
    cat: {
      name: string;
      age: number;
    };
  }
  const animalsInfo: AnimalsInfo = {
    dog: {
      name: "dogName",
      age: 2,
    },
    cat: {
      name: "catName",
      age: 3,
    },
  };
};
(_tip: "Demo1") => {
  type petsGroup = "dog" | "cat";
  interface IPetInfo {
    name: string;
    age: number;
  }
  type IPets = Record<petsGroup, IPetInfo>;
  const animalsInfo = {
    dog: {
      name: "dogName",
      age: 2,
    },
    cat: {
      name: "catName",
      age: 3,
    },
  };
};
(_tip: "Demo2") => {
  type petsGroup = "dog" | "cat";
  interface IPetInfo {
    name: string;
    age: number;
  }
  type IPets = Record<petsGroup | "otherAnamial", IPetInfo>;
  const animalsInfo: IPets = {
    dog: {
      name: "dogName",
      age: 2,
    },
    cat: {
      name: "catName",
      age: 3,
    },
    otherAnamial: {
      name: "otherAnamialName",
      age: 10,
    },
  };
};

/**
 * Omit<K, U>
 *  返回移除 K 对象中的 U 属性后的新类型
 */

(_tip: "源码") => {
  type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
};
(_tip: "使用") => {
  type Foo = Omit<{name: string, age: number}, 'name'> // { age: number }
};

/**
 * 技巧
 *  数组类型明文确认长度
 */
before => {
  const data = [
    [1, 5.5],
    [2, 3.7],
    [3, 2.0],
    [4, 5.9],
    [5, 3.9],
  ];
};
after => {
  interface CharData extends Array<number> {
    0: number;
    1: number;
    length: 2;
  }
  const data2: CharData[] = [
    [1, 5.5],
    [2, 3.7],
    [3, 2.0],
    [4, 5.9],
    [5, 3.9],
  ];
};
(ts 3.0+) => {
  type Tuple<TItem, TLength extends number> = [TItem, ...TItem[]] & {
    length: TLength;
  };
  const data3: Tuple<number,2>[] = [
      [1, 5.5],
      [2, 3.7],
      [3, 2.0],
      [4, 5.9],
      [5, 3.9],
    ];
  tips: ts 3.0在元组类型中引入了其余元素
  // https://stackoverflow.com/questions/52489261/typescript-can-i-define-an-n-length-tuple-type
}

/**
 * 技巧
 *  巧用查找类型
 */
before => {
  interface Person {
    addr: {
      city: string;
      street: string;
      num: number;
    };
  }
  interface Address {
    city: string;
    street: string;
    num: number;
  }
  const Addr: Address = {
    city: "city",
    street: "street",
    num: 0,
  };
};
after => {
  interface Person {
    addr: {
      city: string;
      street: string;
      num: number;
    };
  }
  const Addr: Person["addr"] = {
    city: "city",
    street: "street",
    num: 0,
  };
};

/**
 * 技巧
 *  找到 Object rest 类型
 */
//
before => {
  interface XYZ {
    x: number;
    y: number;
    z: number;
  }
  const restObj: XYZ = { x: 1, y: 2, z: 3 };
  const { x, y, z, ...rest } = restObj;
  function dropXYZ(restObj: XYZ, ...rest) {
    return rest;
  }
};
// after (Pick , Exclude)
after => {
  interface XYZ {
    x: number;
    y: number;
    z: number;
  }

  type DropXYZ<T> = Pick<T, Exclude<keyof T, keyof XYZ>>;

  function _dropXYZ<T extends XYZ>(
    restObj: XYZ,
    ...rest: Array<DropXYZ<T>>
  ): Array<DropXYZ<T>> {
    return rest;
  }
};



结束了?

...

还有个小彩蛋~

这里有个关于 Promise 的小题目:


  const p1 = new Promise((resolve,reject) => {
    console.log('Promise 1');
    resolve();
  }).then(() => {
    console.log('then 11');
    const p2 = new Promise((resolve,reject) => {
      console.log('Promise 2');
      resolve();
    }).then(() => {
      console.log('then 21');
    }).then(() => {
      console.log('then 22');
    })
  }).then(() => {
    console.log('then 12')
  })
目录
相关文章
|
2月前
|
JavaScript
typeScript进阶(9)_type类型别名
本文介绍了TypeScript中类型别名的概念和用法。类型别名使用`type`关键字定义,可以为现有类型起一个新的名字,使代码更加清晰易懂。文章通过具体示例展示了如何定义类型别名以及如何在函数中使用类型别名。
39 1
typeScript进阶(9)_type类型别名
|
2月前
|
JavaScript
typeScript基础(2)_any任意值类型和类型推论
本文介绍了TypeScript中的`any`任意值类型,它可以赋值为其他任何类型。同时,文章还解释了TypeScript中的类型推论机制,即在没有明确指定类型时,TypeScript如何根据变量的初始赋值来推断其类型。如果变量初始化时未指定类型,将被推断为`any`类型,从而允许赋予任何类型的值。
55 4
|
23天前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
37 0
|
23天前
|
JavaScript 前端开发 开发者
深入理解TypeScript:类型系统与实用技巧
【10月更文挑战第8天】深入理解TypeScript:类型系统与实用技巧
|
2月前
|
JavaScript
typeScript基础(5)_对象的类型-interfaces接口
本文介绍了TypeScript中接口(interfaces)的基本概念和用法,包括如何定义接口、接口的简单使用、自定义属性、以及如何使用`readonly`关键字定义只读属性。接口在TypeScript中是定义对象形状的重要方式,可以规定对象的必有属性、可选属性、自定义属性和只读属性。
38 1
|
2月前
|
存储 JavaScript
typeScript进阶(11)_元组类型
本文介绍了TypeScript中的元组(Tuple)类型,它是一种特殊的数组类型,可以存储不同类型的元素。文章通过示例展示了如何声明元组类型以及如何给元组赋值。元组类型在定义时需要指定数组中每一项的类型,且在赋值时必须满足这些类型约束。此外,还探讨了如何给元组类型添加额外的元素,这些元素必须符合元组类型中定义的类型联合。
44 0
|
2月前
|
JavaScript
typeScript进阶(10)_字符串字面量类型
本文介绍了TypeScript中的字符串字面量类型,这种类型用来限制变量只能是某些特定的字符串字面量。通过使用`type`关键字声明,可以确保变量的值限定在预定义的字符串字面量集合中。文章通过示例代码展示了如何声明和使用字符串字面量类型,并说明了它在函数默认参数中的应用。
35 0
|
6天前
|
JavaScript 开发者
在 Babel 插件中使用 TypeScript 类型
【10月更文挑战第23天】可以在 Babel 插件中更有效地使用 TypeScript 类型,提高插件的开发效率和质量,减少潜在的类型错误。同时,也有助于提升代码的可理解性和可维护性,使插件的功能更易于扩展和升级。
|
18天前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
20天前
|
JavaScript 前端开发 安全
TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!