详解Typescript常用的高级类型


2020-06-29 TS JS

TS中有官方给出的高级类型来辅助我们日常开发,但是无论是书本还是文档讲的都不是很清晰,网上的文章更是生涩难懂,故写下这篇文章来记录和帮助需要的人。

# 前置知识:keyof

首先在了解高级类型之前要先理解keyof:

interface User {
  name: string;
  mobile: string;
}

type keys = keyof User; // 相当于type keys = 'name' | 'mobile'

从上面可以看出,keyof是取interface的键。理解了keyof才能理解后面的高级类型:Record、Pick。

# 前置知识:Mapped types

Mapped types是Typescript的映射类型,能够让你快速创建类型:

type NewUser = {
  [K in 'name' | 'mobile']: string;
};

// 上面的代码等同于:
type NewUser = {
  name: string;
  mobile: string;
}

根据上面的keyof我们也可以:

interface User {
  name: string;
  mobile: string;
}

type NewUser = {
  [K in keyof User]: string;
};

前置知识已经学完了,后面我们可以进入主题学习Typescript的高级类型了。

# Record类型

Record类型是最常用的类型,可以快速创建一个类型,我们先来看Record的源码:

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

看代码其实已经很明显了,结合上面的前置知识的代码,我们可以直接示例:


type User = Record<'name' | 'mobile', string>;

// 上面的代码相当于
type User = {
  name: string;
  mobile: string;
}

# Partial类型

Partial类型是将类型的所有属性都修改为可选。源码如下:

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

Partial的使用如下:

type User = {
  name: string;
  mobile: string;
}

type NewUser = Partial<User>;

// 相当于
type NewUser = {
  name?: string;
  mobile?: string;
}

结合Record我们也可以这样:

type NewUser = Partial<Record<'name' | 'mobile', string>>;

# Readonly类型

Readonly类型就跟名字一样,将传入的类型的所有属性都定义为只读。源码如下:

/**
 * Make all properties in T readonly
 */
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

具体使用如下:

type User = Readonly<Record<'name' | 'mobile', string>>;

// 等同于
type User = {
  readonly name: string;
  readonly mobile: string;
}

# Pick类型

Pick类型是将传入的类型,选择一个指定的类型然后返回一个新的类型。源码如下:

/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

具体使用如下:

type User = {
  name: string;
  mobile: string;
  address: string;
}

type NewUser = Pick<User, 'name' | 'mobile'>;

// 相当于
type NewUser = {
  name: string;
  mobile: string;
}

# 总结

其实这些高级类型Typescript在2016年就给出了,所以早就被应用在了一些包和框架上,这些类型其实在日常的开发中也是能够用到的,故记录下来。