TypeScript 實(shí)用工具類型
作者:forceddd
來(lái)源:SegmentFault 思否社區(qū)
Partial<Type>
構(gòu)造類型Type,并將它所有的屬性設(shè)置為可選的。它的返回類型表示輸入類型的所有子類型。
例子
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
title: 'organize desk',
description: 'clear clutter',
};
const todo2 = updateTodo(todo1, {
description: 'throw out trash',
});
Readonly<Type>
構(gòu)造類型Type,并將它所有的屬性設(shè)置為readonly,也就是說(shuō)構(gòu)造出的類型的屬性不能被再次賦值。
例子
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: 'Delete inactive users',
};
todo.title = 'Hello'; // Error: cannot reassign a readonly property
這個(gè)工具可用來(lái)表示在運(yùn)行時(shí)會(huì)失敗的賦值表達(dá)式(比如,當(dāng)嘗試給凍結(jié)對(duì)象的屬性再次賦值時(shí))。
Object.freeze
function freeze<T>(obj: T): Readonly<T>;
Record<Keys, Type>
構(gòu)造一個(gè)類型,其屬性名的類型為K,屬性值的類型為T。這個(gè)工具可用來(lái)將某個(gè)類型的屬性映射到另一個(gè)類型上。
例子
interface PageInfo {
title: string;
}
type Page = 'home' | 'about' | 'contact';
const x: Record<Page, PageInfo> = {
about: { title: 'about' },
contact: { title: 'contact' },
home: { title: 'home' },
};
Pick<Type, Keys>
從類型Type中挑選部分屬性Keys來(lái)構(gòu)造類型。
例子
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
Omit<Type, Keys>
從類型Type中獲取所有屬性,然后從中剔除Keys屬性后構(gòu)造一個(gè)類型。
例子
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, 'description'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
Exclude<Type, ExcludedUnion>
從類型Type中剔除所有可以賦值給ExcludedUnion的屬性,然后構(gòu)造一個(gè)類型。
例子
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
Extract<Type, Union>
從類型Type中提取所有可以賦值給Union的類型,然后構(gòu)造一個(gè)類型。
例子
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
NonNullable<Type>
從類型Type中剔除null和undefined,然后構(gòu)造一個(gè)類型。
例子
type T0 = NonNullable<string | number | undefined>; // string | number
type T1 = NonNullable<string[] | null | undefined>; // string[]
Parameters<Type>
由函數(shù)類型Type的參數(shù)類型來(lái)構(gòu)建出一個(gè)元組類型。
例子
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
// []
type T1 = Parameters<(s: string) => void>;
// [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
// [arg: unknown]
type T3 = Parameters<typeof f1>;
// [arg: { a: number; b: string; }]
type T4 = Parameters<any>;
// unknown[]
type T5 = Parameters<never>;
// never
type T6 = Parameters<string>;
// never
// Type 'string' does not satisfy the constraint '(...args: any) => any'.
type T7 = Parameters<Function>;
// never
// Type 'Function' does not satisfy the constraint '(...args: any) => any'.
ConstructorParameters<Type>
由構(gòu)造函數(shù)類型來(lái)構(gòu)建出一個(gè)元組類型或數(shù)組類型。
由構(gòu)造函數(shù)類型Type的參數(shù)類型來(lái)構(gòu)建出一個(gè)元組類型。(若Type不是構(gòu)造函數(shù)類型,則返回never)。
例子
type T0 = ConstructorParameters<ErrorConstructor>;
// [message?: string | undefined]
type T1 = ConstructorParameters<FunctionConstructor>;
// string[]
type T2 = ConstructorParameters<RegExpConstructor>;
// [pattern: string | RegExp, flags?: string | undefined]
type T3 = ConstructorParameters<any>;
// unknown[]
type T4 = ConstructorParameters<Function>;
// never
// Type 'Function' does not satisfy the constraint 'new (...args: any) => any'.
ReturnType<Type>
由函數(shù)類型Type的返回值類型構(gòu)建一個(gè)新類型。
例子
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<(<T>() => T)>; // {}
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
type T4 = ReturnType<typeof f1>; // { a: number, b: string }
type T5 = ReturnType<any>; // any
type T6 = ReturnType<never>; // any
type T7 = ReturnType<string>; // Error
type T8 = ReturnType<Function>; // Error
InstanceType<Type>
由構(gòu)造函數(shù)類型Type的實(shí)例類型來(lái)構(gòu)建一個(gè)新類型。
例子
class C {
x = 0;
y = 0;
}
type T0 = InstanceType<typeof C>; // C
type T1 = InstanceType<any>; // any
type T2 = InstanceType<never>; // any
type T3 = InstanceType<string>; // Error
type T4 = InstanceType<Function>; // Error
Required<Type>
構(gòu)建一個(gè)類型,使類型Type的所有屬性為required。
與此相反的是Partial。
例子
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 }; // OK
const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
ThisParameterType<Type>
從函數(shù)類型中提取 this 參數(shù)的類型。
若函數(shù)類型不包含 this 參數(shù),則返回 unknown 類型。
例子
function toHex(this: Number) {
return this.toString(16);
}
function numberToString(n: ThisParameterType<typeof toHex>) {
return toHex.apply(n);
}
OmitThisParameter<Type>
從Type類型中剔除 this 參數(shù)。
若未聲明 this 參數(shù),則結(jié)果類型為 Type 。
否則,由Type類型來(lái)構(gòu)建一個(gè)不帶this參數(shù)的類型。
泛型會(huì)被忽略,并且只有最后的重載簽名會(huì)被采用。
例子
function toHex(this: Number) {
return this.toString(16);
}
const fiveToHex: OmitThisParameter<typeof toHex> = toHex.bind(5);
console.log(fiveToHex());
ThisType<Type>
這個(gè)工具不會(huì)返回一個(gè)轉(zhuǎn)換后的類型。
它作為上下文的this類型的一個(gè)標(biāo)記。
注意,若想使用此類型,必須啟用--noImplicitThis。
例子
// Compile with --noImplicitThis
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
};
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; // Strongly typed this
this.y += dy; // Strongly typed this
},
},
});
obj.x = 10;
obj.y = 20;
obj.moveBy(5, 5);
上面例子中,makeObject參數(shù)里的methods對(duì)象具有一個(gè)上下文類型ThisType<D & M>,因此methods對(duì)象的方法里this的類型為{ x: number, y: number } & { moveBy(dx: number, dy: number): number }。
在lib.d.ts里,ThisType<T>標(biāo)識(shí)接口是個(gè)簡(jiǎn)單的空接口聲明。除了在被識(shí)別為對(duì)象字面量的上下文類型之外,這個(gè)接口與一般的空接口沒(méi)有什么不同。

