TypeScript - 泛型工具

前言

本文主要记录下 TypeScript 中常用的泛型工具,日常学习总结篇。

一、extends

这里主要介绍下 extends 关键字在 TS 中的两种用法,即接口继承和条件判断。

1⃣️、接口继承

extends 做继承功能,同 ES6 的 Class 语法用它来做类的继承用法类似。实例代码如下:

interface IName {
  name: string
}

interface IAge {
  age: number
}

interface IPerson extends IAge, IName {
  sex: string
}

const obj: IPerson  = {
  age: 18,
  name: 'Jenny',
  sex: '女'
}

上述代码中,IAge 和 IName 两个接口,分别定义了 age,name属性,IPerson 则使用 extends 多重继承的方法,继承了 IAge 和 IName,同时定义了自身属性 sex,此时 IPerson 除了自身属性外,还同时拥有了来自 IAge 和 IName 的属性。

2⃣️、条件判断

条件判断会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一。

T extends U ? X : Y

上述代码含义为:如果 T 包含的类型是 U 包含的类型的 '子集',那么取结果 X,否则取结果 Y。

实现一个简单的示例代码:

type WhatType = T extends null | undefined ? never : T

let typeString: WhatType = 'abc' // string 类型
let typeNull: WhatType // never 类型

上述代码含义为:如果泛型参数 T 为 null 或 undefined,那么取 never,否则直接返回 T。

二、infer

在条件类型语句中,可以用 infer 声明一个类型变量,并且对它进行使用。

infer 可以在 extends 的条件语句中推断待推断的类型。示例代码如下:

type ParamType = T extends (...args: infer P) => any ? P : T;

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

type Func = (user: User) => void;

type Param = ParamType; // Param = User
type AA = ParamType; // string

三、keyof - 枚举类型(可以理解为 keyof 对象类型

keyof 操作符用来获取某种类型的所有 key 值,返回一个联合类型。示例代码如下:

interface IPerson {
  name: string,
  age: number
}

type allKey1 = keyof IPerson // 'name' | 'age'

type allKey2 = keyof IPerson[] // 'length | 'toString | 'pop' | 'push' | 'concat' | 'join' | ......

type allKey3 = keyof { [x: string]: IPerson } // string | number

四、typeof

typeof 操作符用来在类型上下文中获取变量或者属性的类型。示例代码如下:

interface IPerson {
  name: string,
  age: number
}

const user: IPerson = {
  name: 'jenny',
  age: 18
}

type student = typeof user // IPerson

五、in - 枚举类型

in 操作符用来遍历枚举类型。示例代码如下:

type keys = 'a' | 'b' | 'c'

type obj = {
  [p in keys]: any
} // { a: any, b: any, c: any}

六、Partial - 对象类型

Partial 的作用是将某个类型里的属性全部变成可选,该方法是联合了 keyof 和 in 实现的。

type Partial = {
    [P in keyof T]?: T[P]  
}

以上代码中,首先通过 keyof T 拿到 T 的所有属性名,然后使用 in 进行遍历,将值赋给 P,最后通过 T[P] 取得相应的属性值。中间的 ? 号,用于将所有属性变为可选。示例代码如下:

interface IPerson {
  name: string,
  age: number
}

type person = Partial

// 相当于
// type person = {
//   name?: string | undefined;
//   age?: number | undefined;
// }

七、Required - 对象类型

Required 的作用就是将某个类型中的属性全部变为必选。

type Required = {
    [P in keyof T]-?: T[P];
};

-? 的作用就是把可选属性的可选性去掉,使该属性变成必选项。示例代码如下:

interface IPerson {
  name?: string,
  age?: number
}

type person = Required

// 相当于
// type person = {
//   name: string;
//   age: number;
// }

八、Readonly - 对象类型

Readonly 的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。

type Readonly = {
    readonly [P in keyof T]: T[P]
}

在每一个 key 前面加上 readonly。示例代码如下:

interface IPerson {
  name: string,
  age: number
}

type person = Readonly

// 相当于
// type person = {
//   readonly name: string;
//   readonly age: number;
// }

const obj:person = {
  name: 'lucy',
  age: 18
}
// 此处 TS 会报错:无法为 name 重新赋值,因为它是只读属性
obj.name="jenny"

九、Mutable - 对象类型

 Mutable 的作用是将 T 中所有属性的 readonly 移除。

type Mutable = {
    -readonly [P in keyof T]: T[P]
}

在每一个 key 前面加上 -readonly。示例代码如下:

interface IPerson {
  readonly name: string,
  readonly age: number
}

type person = Mutable

// 相当于
// type person = {
//   name: string;
//   age: number;
// }

十、Exclude - 枚举类型

Exclude 的作用是将某个类型中属于另一个的类型移除掉。

type Exclude = T extends U ? never : T;

实现效果为从 T 中去除 T 与 U 的交集后的类型。示例代码如下:

type exclude0 = Exclude // string | boolean

type exclude1 = Exclude<'a' | 'b' | 'c', 'a' | 'c'> // 'b'

十一、Extract - 枚举类型

Extract 的作用是将某个类型中属于另一个的类型提取出来。

type Extract = T extends U ? T : never;

这个和上面的 Exclude 恰好相反,实现效果为从 T 中提取 T 与 U 的交集类型。示例代码如下:

type extract0 = Extract // number

type extract1 = Extract<'a' | 'b' | 'c', 'a' | 'c'> // 'a' | 'c

十二、Pick - 对象类型

Pick 的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子属性。

type Pick = {
    [P in K]: T[P]
}

T 是多类型,K 是 T 的部分类型,然后遍历 K 拿到键,再去 T 里拿到相应的值。简单来说就是:

从 T 中提取出 T 与 K 属性值相同的属性。示例代码如下:

interface IPerson {
  name: string,
  age: number,
  sex: string
}

type person = Pick

const user: person = {
  name: 'jenny',
  age: 18 // TS 提示报错,age 不在 person 类型中
}

Pick 与 Extract 都有从 T 中提取 T 与 K 相交的那部分,它们的区别在于 Pick 作用于对象类型,返回的类型用于定义对象;Extract 作用与枚举类型,返回的类型用于定义枚举类型变量。

十三、Record

Record 的作用是将 K 中所有的属性的值转换为 T 类型。

type Record = {
    [P in K]: T
}

将 K 中有类型的属性进行遍历,再将每个 key 赋值为 T 类型。示例代码如下:

type record0 = Record<'a' | 'b', number>

// 相当于
// type record0 = {
//   a: number,
//   b: number
// }

十四、Omit

Omit 的作用是使用 T 类型中除了 K 类型的所有属性。

type Omit = Pick>

实现效果为从对象 T 中剔除 key 为 K 中的属性。

interface IPerson {
  name: string,
  age: number,
  sex: string
}

type person = Omit

// 相当于
// type person = {
//   age: number,
//   sex: string
// }

十五、ReturnType

ReturnType 的作用是用于获取函数 T 的返回类型。

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

示例代码如下:

type T1 = ReturnType<() => string> // string

type T2 = ReturnType<(s: string) => void> // void

十六、 NonNullable - 枚举类型

NonNullable 的作用是剔除 T 为 null、undefined 的类型。

type NonNullable = T extends null | undefined ? never : T;

示例代码如下:

type T = NonNullable // string | string[]

你可能感兴趣的:(TypeScript,typescript,前端)