ts 常用的工具泛型及其源码

泛型对前端开发人员来说会比较陌生,其实它可以被理解成是一种预先设置的数据类型,在后面通过推导得出真实的类型后再替换。在 typescript 中有很多的工具泛型,可以帮助我们更加灵活地处理类型,简化类型编程的过程,提高生产力。

关键词

要熟悉工具泛型及其原理,首先要掌握 typescript 的关键词

typeof

获取变量的类型

keyof

keyof T,获取类型 T 的所有键组成的联合类型,keyof 也被称为 索引类型查询操作符

interface IPerson {
  id: string;
  age: number;
}

type IPersonKeys = keyof IPerson; // 'id' | 'age'
type IPersonKeys = IPerson[keyof IPerson]; // string | number

[]

索引访问操作符,可以进行索引访问

interface T {
  K: string;
}

type TypeK = T[K]; // string

in

可以对联合类型进行遍历。通过 [K in Keys] 可以实现映射类型,从旧类型中创建新类型的一种方式

type Index = 'a' | 'b' | 'c'
type FromIndex = { [K in Index]?: number }

const index_1: FromIndex = { b: 1, c: 2 }
const index_2: FromIndex = { b: 1, d: 3 } // 报错,不能添加d属性

extends

  1. 用来扩展已有的类型
interface IAnimal = {
  name: string;
}
interface ICat extends IAnimal {
  action: string;
}

// 等价于
type ICat = IAnimal & {
  action: string;
}
  1. 对类型进行条件限定,比如判断两种类型是否相等:
type IsEqualType<A, B> = A extends B ? (B extends A ? true : false) : false;
  1. 对于 T extends U ? X : Y 来说,还存在一个特性,当 T 是一个联合类型时,会进行条件分发。这一点对于理解后面的工具泛型很关键
type Demo = string | number;
type IsString<T> = T extends string ? "yes" : "no";

type IsDemoString = IsString<Demo>; // 'yes' | 'no';

实际上,extends 的转换类似于下面这一步:

(string extends string ? 'yes' : 'no') | (number extends string ? 'yes' : 'no')

infer

在有条件类型的 extends 子语句中,允许出现 infer 声明,它会引入一个待推断的类型变量,简单说就是用它取到函数返回值的类型来使用

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

readonly

将属性标记为只读

工具泛型

Record

将 K 中所有的属性的值转化为 T 类型

type Record<K extends keyof any, T> = { [P in K]: T };

Pick

从 T 中取出一系列 K 的值

type Pick<T, K extends keyof T> = { [P in K]: T[P] };

Exclude

从 T 中排除 U

type Exclude<T, U> = T extends U ? never : T;

Extract

从 T 中提取 U

type Extract<T, U> = T extends U ? T : never;

Omit

相当于 Pick + Exclude, 实现忽略对象某些属性功能,Pick+Exclude

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

Partial

将 T 中的属性都变为可选属性

type Partial<T> = { [k in keyof T]?: T[k] };

Required

将 T 中的属性都变为必选属性

type Required<T> = { [k in keyof T]-?: T[k] };

Readonly

将 T 中的属性都变为只读属性

type Readonly<T> = { readonly [k in keyof T]: T[k] };

Mutable

将 T 中的属性都变为可读属性

type Mutable<T> = { -readonly [k in keyof T]: T[k] };

ReturnType

获取函数的返回值的类型

type ReturnType<T extends (...args: any[]) => any> = T extends (
  ...args: any[]
) => infer R
  ? R
  : never;

Parameters

获取函数的参数的类型

type Parameters<T extends (...args: any[]) => any> = T extends (
  ...args: infer P
) => any
  ? P
  : never;