🐈 Axnir's Site

TypeScript 的一些工具泛型

2021/05/27

先来看一下它们的源码

/**
 * 让 T 中所有属性都变为可选
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

/**
 * 让 T 中所有属性都变为只读
 */
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

/**
 * 从 T 中,选取指定一组属性,返回一个新的类型定义。
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

/**
 * 构造一个 key 是 K 中属性且类型是 T 的类型
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

/**
 * 从 T 中找出 U 中没有的元素(从 T 中排除 U )
 */
type Exclude<T, U> = T extends U ? never : T;

/**
 * 从 T 中找出 U 中有的元素(从 T 中取出 U )
 */
type Extract<T, U> = T extends U ? T : never;

/**
 * 从 T 中取出 K 中没有的属性(忽略 K 中存在的属性)
 */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

/**
 * 获取函数的返回类型
 */
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

Record

以 keyof 格式快速创建一个类型,此类型包含一组指定的属性且都是必填。

type k1 = Record<string | number, number | string>

// 相当于
type k1 = {
    [x: string]: string | number,
    [x: number]: string | number,
}

Partial

将类型定义的所有属性都修改为可选。

interface Person {
    name: string,
    age: number
}

type k1 = Partial<Person>

// 等同于
type k1 = {
	name?: string;
	age?: number;
}

Readonly

将类型定义的所有属性改为只读。

interface Person {
    name: string,
    age: number
}

type k1 = Readonly<Person>;

// 等同于
type k1 = {
    readonly name: string;
    readonly age: number;
}

Pick

从类型定义的属性中,选取指定一组属性,返回一个新的类型定义。

interface Person {
    name: string,
    age: number
}

type k1 = Pick<Person, 'name'>

// 相当于
type k1 = {
	name: string
}

Exclude

从 T 中找出 U 中没有的元素(通俗来讲就是从 T 中排除 U )。

type k1 = Exclude<'name' | 'age', 'name'>

// 相当于
type k1 = 'age'

Extract

作用与 Exclude 相反,从 T 中找出 U 中有的元素(通俗来讲就是从 T 中取出 U )。

type k1 = Extract<'name' | 'age', 'name'>

// 相当于
type k1 = 'name'

Omit

PickExclude 进行组合, 忽略对象某些属性功能。

type k1 = Omit<{name: string, age: number}, 'name'>

// 相当于
type k1 = {
	age: number
}

ReturnType

获取函数的返回类型。

理解 ReturnType 需要先来了解 infer , infer 表示在 extends 条件语句中待推断的类型变量。

一个例子:

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

type fn = (str: string) => void;

type k1 = ParamType<fn> // string,返回了 fn 类型参数的类型

如果 T 能赋值给 (...args: infer P) => any,则结果是 (...args: infer P) => any 类型中的参数 P,否则返回为 T。

再回到 ReturnType,如果传入的是一个函数就返回函数的返回值的类型,否则返回 any

// getInt 函数接收一个字符串,然后将其转换成整数值
const getInt = (str: string) => {
  return parseInt(str);
};

type k1 = ReturnType<typeof getInt>; // number