关于typescript:TypeScript-工具泛型

48次阅读

共计 3375 个字符,预计需要花费 9 分钟才能阅读完成。


highlight: github

theme: juejin

前言

Typescript 中默认内置了很多工具泛型,通过应用这些工具,能够使得咱们定义类型更加灵便,高效。本文将会介绍罕用泛型工具的应用技巧,以及对其实现原理进行相应的解析,如果有谬误的中央,还望指出。

Partial\<T>

作用 :将传入对象类型 T 的属性变为 可选属性

示例

interface Person {
  name: string;
  age: number;
}

const tom: Partial<Person> = {name: "Tom",};

Partial<Person> 等价于

interface Person {
  name?: string;
  age?: number;
}

实现原理

  1. 通过关键字 keyof 将传入对象类型的键值转换为联结类型。
  2. 通过关键字 in 遍历联结类型,即遍历对象的键值。
  3. 通过类型映射,将对象的属性转换为 可选属性
type MyPartial<T> = {[P in keyof T]?: T[P];
};

Readonly\<T>

作用 :把传入对象类型 T 属性变为 只读属性

示例

interface Person {
  name: string;
  age: number;
}

const tom: Readonly<Person> = {
  name: "Tom",
  age: 18;
};

tom.age = 22 // error

Readonly<Person> 等价于

interface Person {
  readonly name: string;
  readonly age: number;
}

实现原理

Partial 相似:

  1. 通过关键字 keyof 将传入对象类型的键值转换为联结类型。
  2. 通过关键字 in 遍历联结类型,即遍历对象的键值。
  3. 通过类型映射,将对象的属性转换为 只读属性
type Readonly<T> = {[P in keyof T]-?: T[P];
};

Required\<T>

作用 :把传入对象类型 T 属性变为 必填属性

示例

interface Person {
  name?: string;
  age?: number;
}

let tom: Required<Person>

tom = {
  name: "Tom",
  age: 18;
};
// ok

tom = {name: "Tom",};
// error

实现原理

Partial 相似:

  1. 通过关键字 keyof 将传入对象的键值转换为枚举类型。
  2. 通过关键字 in 遍历枚举类型,即遍历对象的键值。
  3. 通过类型映射,再对立通过 -? 修饰符移除 ? 修饰符,从而转变为 必填状态
type Required<T> = {Required [P in keyof T]: T[P];
};

Record\<K,T>

作用:它用来生成一个属性名为 K,属性值类型为 T 的对象类型汇合。

示例

// 疾速生成一个 Person 对象
type Person = Record<"name" | "country", string>;

const Tom: Person = {name: "Tom", country: "America"};

实现原理:

  1. 通过 K extends keyof anyK 参数进行束缚,将其束缚为任意类型 any 的键值。
  2. 通过 in 对键值汇合 K 进行遍历,而后生成类型为 T 的键值对汇合。
type MyRecord<K extends keyof any, T> = {[P in K]: T;
};

Exclude\<T,K>

作用:从类型 T 中排除所有能够赋值给类型 U 的类型。

示例

// 从 "a" | "b" | "c" 中排除掉 "a" 类型
type T1 = Exclude<"a" | "b" | "c", "a">;
// T1 = "b" | "c"

// 从 string | number | boolean 中排除掉 string 类型
type T2 = Exclude<string | number | boolean, string>;
// T2 = number | boolean

实现原理

  1. 通过条件类型T extends U ? never : TT 参数进行判断:

    • 如果 T 可赋值给 U,那么返回 never(即排除掉T)。
    • 如果 T 不可赋值给 U,那么返回 T
  2. 通过 分布式条件类型 ,如果 T 为联结类型,则将条件类型的后果散发为 联结类型
type Exclude<T, U> = T extends U ? never : T;

Extract\<T,K>

作用:与 Exclude 相同,从类型 T 中提取所有能够赋值给类型 U 的类型。

示例

// 从 "a" | "b" | "c" 中提取出 "a" 类型
type T1 = Extract<"a" | "b" | "c", "a">;
// T1 = "a"

// 从 string | number | boolean 中提取出 string 类型
type T2 = Extract<string | number | boolean, string>;
// T2 = string

type T3 = Extract<string | (() => void), Function>;
// 相当于 type T3 = () => void;

实现原理

Exclude 相似:

  1. 通过条件类型T extends U ? never : TT 参数进行判断:

    • 如果 T 可赋值给 U,那么返回 T
    • 如果 T 不可赋值给 U,那么返回 never(即排除掉T)。
  2. 通过 分布式条件类型 ,如果 T 为联结类型,则将条件类型的后果散发为 联结类型
type Extract<T, U> = T extends U ? T : never;

Pick\<T,K>

作用:在 T 中,摘选出 K 属性。

示例

interface Person {
  name: string;
  age: number;
}

// 从 Person 中摘选出 name 属性
type PickPerson = Pick<Person, "name">;

const tom: PickPerson = {name: "Tom",};

实现原理

  1. 通过 K extends keyof TK 参数进行束缚,将其束缚为 T 的键值范畴内。
  2. 通过 in 对键值汇合 K 进行遍历,而后生成类型为 T 的键值对汇合。
type Pick<T, K extends keyof T> = {[P in K]: T[P];
};

Omit\<T,K>

作用:在 T 中,剔除掉 K 属性。

示例

interface Person {
  name: string;
  age: number;
}

// 从 Person 中剔除掉 name 属性
type OmitPerson = Omit<Person, "name">;

const tom: OmitPerson = {age: 18,};

实现原理

  1. 通过 K extends keyof TK 参数进行束缚,将其束缚为 T 的键值范畴内。
  2. 通过 Exclude<keyof T, K> 将类型汇合 T 中的 K 类型排除掉。
  3. 通过 Pick<T,Exclude<keyof T, K>>T 中摘选出排除掉 KT 的属性。
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

ReturnType\<T>

作用:获取函数的返回值类型。

示例

type Fun = () => string;

// 获取 Fun 返回值的类型
type T1 = ReturnType<Fun>; // T1 = string

type T2 = ReturnType<() => { x: number; y: number}>;
// T2 = {x: number, y: number}

实现原理

  1. 通过 extendsT 参数进行束缚,(...args: any) => any 示意一个函数类型,即 T 参数的类型必须是一个 函数类型
  2. T extends U ? X : Y 是条件类型(留神和之前示意束缚的 extends 做辨别),其中 T 是泛型参数,U 条件局部X 是符合条件的返回后果,Y 是不符合条件的返回后果。
  3. 推断类型 infer 的作用是:在条件类型外部申明一个 类型变量 (...args: any) => infer R 是条件类型的 条件局部,它申明了一个类型变量 R,用来存储函数的返回类型。
  4. T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any示意:

    • 如果 T 是函数类型((...args: any) => infer R),则返回 R , 即函数的返回类型。
    • 如果 T 不是函数类型((...args: any) => infer R),则返回 any
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R
  ? R
  : any;

参考资料

  • TypeScript 中文手册
  • TypeScript 内置工具泛型

正文完
 0