TypeScript 的全部 高級類型

既然官方提供的高級類型並很少,那麼就把他們所有都說明一遍吧,讓咱們在開發中更加效率。其中 Typescript 中的 Partial, Readonly, Record, Pick 中已經對這4個使用頻率最高的進行了說明,所以這裏再也不重複。html

備註:高級類型聲明中,涉及到的 條件類型、映射類型、類型推斷、never 類型,以前的均有分享,你能夠在個人專欄裏看到。(其實,以前解讀的這些就是爲介紹官方的高級類型作前提)typescript

這些高級類型可能你並不會用到,但簡單過一遍知道 TS 預置了哪些就行,當某些開放場景想起時,總會帶來驚喜。(編寫這些特性的是基於 v3.8-Beta版本)c#

Required< T >

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

Partial<T> 程序類型的做用相反,將類型屬性都變成必填。app

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

// 等同於
type Coord = {
	x: number;
	y: number;
}
複製代碼

主要是由於 -? 映射條件的裝飾符的能力,去掉了全部可選參數狀態,更多的裝飾符說明能夠以前分享的 TypeScript 的映射類型 Mapped types (e.g. { [P in K]: T[P] })函數

Exclude<T, U>

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

排除一個 聯合類型 中指定的子類型:post

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

主要是基於 extends 條件類型的解析推遲的特性,返回了匹配以外的全部 候選類型,配合 never 類型 的空值特性,實現了這一高級類型。ui

Extract<T, U>

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

Exclude<T, U> 徹底相反的功能,用於提取指定的 聯合類型,若是不存在提取類型,則返回never。能夠用在判斷一個複雜的 聯合類型 中是否包含指定子類型:this

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

Omit<T, K extends keyof any>

/** * 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>>;
複製代碼

排除接口中指定的屬性:spa

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 }
複製代碼

這個在高級類型的使用頻率也比較高。code

NonNullable< T >

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

過濾掉 聯合類型 中的 nullundefined 類型:

type T1 = NonNullable<string | null | undefined>; // string
複製代碼

額外說明下,由於 nullundefined 類型的特殊性,他們能夠賦值給任何類型,這每每會帶來意料以外的錯誤。當你開啓 --strictNullChecks 設置後,TS 就會嚴格檢查,只有被聲明 null 後才能被賦值:

// 關閉 --strictNullChecks
let s: string = "foo";
s = null; // 正常

// 開啓 --strictNullChecks
s = null; // Error: Type 'null' is not assignable to type 'string'. 
複製代碼

Parameters<T extends (...args: any) => any>

/** * 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]
複製代碼

若是你想了解原理,能夠看以前分享的 TypeScript 條件類型的 infer 類型推斷能力

ConstructorParameters<T extends new (...args: any) => any>

/** * 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]
複製代碼

這裏的 IEntityConstructor 接口用來幹什麼的呢,當基於 建立實例函數 時就派上了用場:

function createEntity(ctor: IEntityConstructor, ...arg: EntityConstructorParamType): IEntity {
    return new ctor(...arg);
}

const entity = createEntity(Entity, true, 'a');
複製代碼

ReturnType<T extends (...args: any) => any>

/** * 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<T extends new (...args: any) => any>

/** * 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< T >

/** * 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< T >

/** * 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
複製代碼
相關文章
相關標籤/搜索