TypeScript 内置工具类型学习(一)

173 阅读4分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

概述

TypeScript内置了很多实用的工具类型,就是将日常开发中会使用到的类型转换进行了封装,并且可以直接全局进行使用。

通过学习这些工具类型可以帮助我们加深对TS类型系统的了解,并运用到实际开发当中。

Partial(将属性变为可选)

Partial<T> 用于将一个类型的所有属性变为可选的。

源码:

type Partial<T> = {
    [P in keyof T]?: T[P];
};
  • {}就代表是声明为一个字面量对象
  • 使用keyofT类型的key遍历出来,并赋值给PP作为新的key
  • 通过T[P]就可以获取到值类型
  • 这时再给键后面加上?就变成可选值了

代码示例:

在线示例

interface User {
  name: string,
  age: number
}

// 报错
const user: User = {

}


type User1 = Partial<User>;

// 不报错,因为属性变为可选了
const user1: User1 = {

}

Required(将属性变为必选)

Required<T>用于将一个类型的所有属性都定义为必不可少的。

源代码:

type Required<T> = {
    [P in keyof T]-?: T[P];
};
  • {}就代表是声明为一个字面量对象
  • 使用keyofT类型的key遍历出来,并赋值给PP作为新的key
  • 通过T[P]就可以获取到值类型
  • 这时再给键后面加上-?就变成必选值了

代码示例:

在线示例

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

// 不报错
const user: User = {
  name: '金小钗'
}


type User1 = Required<User>;

// 报错,因为所有属性都变为必选了
const user1: User1 = {
  name: '金小钗'
}

Readonly(将属性变为只读)

Readonly<T>用于将一个类型的所有属性都定义为只读的。

源代码:

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};
  • {}就代表是声明为一个字面量对象
  • 使用keyofT类型的key遍历出来,并赋值给PP作为新的key
  • 通过T[P]就可以获取到值类型
  • 这时再给键的前面加上readonly就变成只读属性了

代码示例:

在线示例

interface User {
  name: string,
  age: number
}

const user: User = {
  name: '金小钗',
  age: 233
}
// 不报错
user.name = '韩立';


type User1 = Readonly<User>;

const user1: User1 = {
  name: '金小钗',
  age: 233
}
// 报错,因为所有属性都变为只读了
user1.name = '韩立';

Pick(挑选属性作为新类型)

Pick<T, K extends keyof T>可以用来从一个类型中,挑出部分属性来组成一个新的类型。

源代码:

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
  • 通过extends进行限制,K只能由T的键类型组成
  • {}就代表是声明为一个字面量对象
  • 使用in遍历K类型,并赋值给PP作为新的key
  • 通过T[P]就可以获取到对应的值类型

代码示例:

在线示例

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

// 挑选 name 属性组成新的类型
type User1 = Pick<User, 'name'>;

// 报错
const user: User1 = {
  name: '金小钗',
  age: 233,
};

// 正确,User1 只有 name 属性
const user1: User1 = {
  name: '金小钗',
};

Record(创建对象类型)

Record<K extends keyof any, T>可以通过K作为键,T作为值类型来组成一个新的类型。

源代码:

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};
  • K可以是任意类型。
  • {}就代表是声明为一个字面量对象
  • 使用in遍历K类型,并赋值给PP作为新的key
  • T就作为值类型

在线示例

示例 1:

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

// 可以用来限定一个对象的键与值的类型
type User1 = Record<string, User>;

const user: User1 = {
  jack: {
    name: '金小钗',
    age: 233,
  },
};

示例 2:

// 用来限制类型只能是键值组成的对象
type Obj = Record<string, unknown>;

// 正确
const obj: Obj = {
  name: '二愣子'
};

// 报错
const obj1: Obj = [];

Exclude(排除联合类型的部分类型)

Exclude<T, U> = T extends U ? never : T通过条件类型限制,将一个类型中的部分类型进行排除,然后组成一个新的类型。 ​

源代码:

/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;
  • T可以转换成U类型,则返回never类型,否则返回T类型
  • never类型表示永不存在的值的类型,所以相当于将这个类型去除了

代码示例:

在线示例

type T0 = 'a' | 'b' | 'c';

/**
 * 排除类型 c
 * 此时 T1 的类型相当于 type T1 = "a" | "b"
 */
type T1 = Exclude<T0, 'c'>;

const a:T1 = 'a';
const b:T1 = 'b';
// 报错
const c:T1 = 'c';

Extract(提取联合类型的部分类型)

Extract<T, U>是根据条件排除,而Extract就是与其相反,根据条件提取类型,然后组成一个新的类型。 ​

源代码:

/**
 * Extract from T those types that are assignable to U
 */
type Extract<T, U> = T extends U ? T : never;
  • T可以转换成U类型,则返回T类型,否则返回never类型
  • never类型表示永不存在的值的类型,所以相当于将这个类型去除了
  • 最后组成的新类型,都是可以转换成U类型的

代码示例:

在线示例

type T0 = 'd' | 'e' | 'f';

/**
 * 提取类型 d 与 e
 * 时 T1 的类型相当于 type T1 = "d" | "e"
 */
type T1 = Extract<T0, 'd' | 'e'>;

const d:T1 = 'd';
const e:T1 = 'e';
// 报错
const f:T1 = 'f';