Typescript 中的高级类型用法

131 阅读4分钟

前几天,在项目中遇到一些没见过的ts类型工具,发现有些变量的类型都用了这些类型工具,遂学习一下做个记录。

在 ts中定义 interface 时,常常需要对进行二次封装或调整,而 ts 在2.1版本中加入了一些程序类型工具,供开发者方便的进行此类操作。

Record

源码定义:

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

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

举个栗子:

type data = Record<'x' | 'y', number>; 
// 等同于 
type data = { 
    x: number; 
    y: number;
}

Partial

源码定义:

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

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

举个栗子:

type data = Partial<Record<'x' | 'y', number>>; 
// 等同于 
type data = {
    x?: number; 
    y?: number; 
}

Readonly

源码定义:

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

如本意只读一样,将所有属性定义为自读。

举个栗子:

type data = Readonly<Record<'x' | 'y', number>>;
// 等同于 
type data = {
    readonly x: number;
    readonly y: number;
}

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 basicData = Record<'x' | 'y', number>; 
type data = Pick<Coord, 'x'>;

// 等同于 
type data = {
    x: number;
}

Required

源码定义:

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

与 Partial<T> 程序类型的作用相反,将类型属性都变成必填。

举个栗子:

type data = Required<{ x: number, y?:number }>;

// 等同于 
type data = {
    x: number;
    y: number;
}

Exclude

源码定义:

/**
* Exclude from T those types that are assignable to U
*/ 
type Exclude<T, U> = T extends U ? never : T;

排除一个 联合类型 中指定的子类型:

举个栗子:

type T0 = Exclude<'a' | 'b' | 'c', 'b'> // 'a' | 'c'
type T1 = Exclude<string | number | boolean, boolean> // string | number

Extract

源码定义:

/**
* Extract from T those types that are assignable to U
*/ 
type Extract<T, U> = T extends U ? T : never;

与 Exclude<T, U> 完全相反的功能,用于提取指定的 联合类型,如果不存在提取类型,则返回never。可以用在判断一个复杂的 联合类型 中是否包含指定子类型:

举个栗子:

type T0 = Extract<'a' | 'b' | 'c', 'a'> // 'a' 
type T1 = Extract<string | number | boolean, boolean> // boolean

Omit

源码定义:

/**
* Construct a type with the properties of T except for those in type K.
*/ 
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

排除接口中指定的属性:

举个栗子:

interface I1 { 
    a: number; 
    b: string; 
    c: boolean;
}

type AC = Omit<I1, 'b'>; // { a:number; c:boolean } 
type C = Omit<I1, 'a' |'b'> // { c: boolean }

NonNullable

源码定义:

/**
* Exclude null and undefined from T
*/ 
type NonNullable<T> = T extends null | undefined ? never : T;

过滤掉 联合类型 中的 null 和 undefined 类型:

举个栗子:

type T1 = NonNullable<string | null | undefined>; // string

Parameters

源码定义:

/**
* Obtain the parameters of a function type in a tuple
*/ 
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

获取函数的全部参数类型,以 元组类型 返回:

举个栗子:

type F1 = (a: string, b: number) => void;

type F1ParamTypes = Parameters(F1); // [string, number]

ConstructorParameters

源码定义:

/**
* Obtain the parameters of a constructor function type in a tuple
*/ 
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

获取的是 构造函数 的全部参数。

举个栗子:

interface IEntity { 
    count?: () => number 
}

interface IEntityConstructor {
    new (a: boolean, b: string): IEntity; 
}

class Entity implements IEntity {
    constructor(a: boolean, b: string) { } 
}

type EntityConstructorParamType = ConstructorParameters<IEntityConstructor>; // [boolean, string]

// 具体用法
function createEntity(ctor: IEntityConstructor, ...arg: EntityConstructorParamType): IEntity {
    return new ctor(...arg); 
} 

const entity = createEntity(Entity, true, 'a');

ReturnType

源码定义:

/**
* Obtain the return type of a function type
*/ 
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

接收函数声明,返回函数的返回值类型,如果多个类型则以 联合类型 方式返回:

举个栗子:

type F1 = () => Date;

type F1ReturnType = ReturnType<F1>; // Date

InstanceType

源码定义:

/**
* Obtain the return type of a constructor function type
*/ 
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;

获取 构造函数 的返回类型,如果是多个就以 联合类型 的方式返回,我们借用上面的定义:

举个栗子:

type EntityType = InstanceType<IEntityConstructor>; // IEntity

ThisParameterType

源码定义:

/**
* Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter.
*/ 
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;

获取函数中 this 的数据类型,如果没有则返回 unknown 类型:

举个栗子:

interface Foo { 
    x: number; 
}

function fn(this: Foo) {}

type Test = ThisParameterType<typeof fn>; // Foo

因为可以在 TS 声明函数的 this ,此方法用于获取此声明,具体的使用:

fn.bind({ x: 1 }); // 正常

fn.bind({ x: '1' }); // Error: ...Type 'string' is not assignable to type 'number'...

OmitThisParameter

源码定义:

/**
* Removes the 'this' parameter from a function type.
*/ 
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;

移除函数中的 this 数据类型:

举个栗子:

interface Foo { 
    x: number 
};

type Fn = (this: Foo) => void

type NonReturnFn = OmitThisParameter<Fn>; // () => void

// 声明此类的函数类型效果如下:
function f(this: void) {} // 此声明在函数内不可使用 this

本文借鉴了:

TypeScript 的所有 高级类型 - 掘金 (juejin.cn) 作者:nachao