Partial<T>
Partial
用於將類型中全部屬性變爲可選類型:typescript
interface Todo {
title: string;
description: string;
}
const todo1: Todo = {
title: "organize desk",
description: "clear clutter",
};
const todo2: Partial<Todo> = {
description: "throw out trash",
};
複製代碼
實現源碼:函數
type Partial<T> = {
[P in keyof T]?: T[P];
};
複製代碼
Required<T>
Required
用於將類型全部屬性變爲必需類型:ui
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 }; // OK
const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
複製代碼
實現源碼:this
type Required<T> = {
[P in keyof T]-?: T[P];
};
複製代碼
Readonly<T>
Readonly
用於將類型中全部屬性變成只讀類型:spa
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users"
};
todo.title = "Hello"; // Error: cannot reassign a readonly property
複製代碼
實現源碼:code
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
複製代碼
Record<T, K>
Record
用於將T
中全部的屬性轉換爲K
類型:接口
interface PageInfo {
title: string;
}
type Page = "home" | "about" | "contact";
const x: Record<Page, PageInfo> = {
about: { title: "about" },
contact: { title: "contact" },
home: { title: "home" },
};
複製代碼
實現源碼:ip
type Record<K extends keyof any, T> = {
[P in K]: T;
};
複製代碼
Exclude<T, K>
Exclude
用於篩選全部在T
中,但不在K
中的屬性:ci
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number 複製代碼
實現源碼:源碼
type Exclude<T, U> = T extends U ? never : T;
複製代碼
Extract<T, K>
Extract
和Exclude
有些相似,用於篩選既在T
中,又在K
中的屬性:
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
複製代碼
實現源碼:
type Extract<T, U> = T extends U ? T : never;
複製代碼
Pick<T, K>
Pick
用於返回從T
中篩選出K
包含的屬性所組成的類型:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
複製代碼
實現源碼:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
複製代碼
Omit<T, K>
和Pick
相反,忽略K
中包含的屬性:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "Clean room",
completed: false
};
複製代碼
實現源碼:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
複製代碼
能夠看到,Omit
類型就是對以前提到的Pick
和Exclude
的進一步封裝。
NonNullable<T>
NonNullable
用於篩選出T
中不是null
或者undefined
的全部類型:
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
複製代碼
實現源碼:
type NonNullable<T> = T extends null | undefined ? never : T;
複製代碼
Parameters<T>
Parameters
用於篩選函數全部的參數類型,並返回一個由這些參數類型構成的元組:
type T0 = Parameters<() => string>; // []
type T1 = Parameters<(s: string) => void>; // [string]
type T2 = Parameters<<T>(arg: T) => T>; // [unknown]
複製代碼
實現源碼:
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
複製代碼
能夠看到T
被約束必須爲函數類型,若是傳入一個非函數類型會報錯。
ReturnType<T>
ReturnType
用於獲取函數返回值類型:
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
複製代碼
實現源碼:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
複製代碼
T
一樣被約束必須爲函數類型。
ConstructorParameters<T>
ConstructorParameters
和Parameters
十分類似,用於獲取構造函數的全部參數類型:
class Person {
constructor(name: string, age: number) {}
}
type T0 = ConstructorParameters<typeof Person>; // [string, number]
複製代碼
實現源碼:
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
複製代碼
T
被約束爲必須爲構造函數。
InstanceType<T>
InstanceType
用於獲取構造函數的返回值:
class Person {
constructor(name: string, age: number) {}
}
type T0 = InstanceType<typeof Person>; // Person
複製代碼
實現源碼:
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
複製代碼
T
一樣被約束爲必須爲構造函數。
ThisParameterType<T>
ThisParameterType
用於獲取函數的this
參數類型。若是函數未指定this
參數,返回unknown
,須要開啓strictFunctionTypes
才能工做:
function toHex(this: Number) {
return this.toString(16);
}
type T0 = ThisParameterType<typeof toHex>; // Number
複製代碼
實現源碼:
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any
? U
: unknown;
複製代碼
OmitThisParameter<T>
OmitThisParameter
用於刪除函數中的this
參數,須要開啓strictFunctionTypes
才能工做:
function toHex(this: Number, others: any) {
return this.toString(16);
}
type T0 = typeof toHex; // function toHex(this: Number, others: any): string
type T1 = OmitThisParameter<typeof toHex>; // (others: any) => string
複製代碼
實現源碼:
type OmitThisParameter<T> = unknown extends ThisParameterType<T>
? T
: T extends (...args: infer A) => infer R
? (...args: A) => R
: T;
複製代碼
ThisType<T>
ThisType
並不會轉換類型,而是用於標記函數中this
的類型,相似於指定this
參數。須要開啓noImplicitThis
才能工做:
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // 標記方法的this類型
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
let obj = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // ts能識別this類型
this.y += dy;
}
}
});
複製代碼
methods
使用ThisType
指定this
。因此makeObject
函數調用時,ts就能推斷出methods
中的函數this
類型爲{ x: number, y: number } & { moveBy(dx: number, dy: number): number }
。
在源碼中,ThisType
就是一個空的泛型接口。