既然官方提供的高級類型並很少,那麼就把他們所有都說明一遍吧,讓咱們在開發中更加效率。其中 Typescript 中的 Partial, Readonly, Record, Pick 中已經對這4個使用頻率最高的進行了說明,所以這裏再也不重複。html
備註:高級類型聲明中,涉及到的 條件類型、映射類型、類型推斷、never 類型,以前的均有分享,你能夠在個人專欄裏看到。(其實,以前解讀的這些就是爲介紹官方的高級類型作前提)typescript
這些高級類型可能你並不會用到,但簡單過一遍知道 TS 預置了哪些就行,當某些開放場景想起時,總會帶來驚喜。(編寫這些特性的是基於 v3.8-Beta版本)c#
/** * 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 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 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
複製代碼
/** * 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
/** * Exclude null and undefined from T */
type NonNullable<T> = T extends null | undefined ? never : T;
複製代碼
過濾掉 聯合類型 中的 null
和 undefined
類型:
type T1 = NonNullable<string | null | undefined>; // string
複製代碼
額外說明下,由於 null
和 undefined
類型的特殊性,他們能夠賦值給任何類型,這每每會帶來意料以外的錯誤。當你開啓 --strictNullChecks
設置後,TS 就會嚴格檢查,只有被聲明 null 後才能被賦值:
// 關閉 --strictNullChecks
let s: string = "foo";
s = null; // 正常
// 開啓 --strictNullChecks
s = null; // Error: Type 'null' is not assignable to type 'string'.
複製代碼
/** * 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 類型推斷能力 。
/** * 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');
複製代碼
/** * 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
複製代碼
/** * 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
複製代碼
/** * 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'...
複製代碼
/** * 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
複製代碼