Typescript 工具类型已经内置在 es5 类型声明中,无需定义即可使用。
不需要一次记住所有工具,只需留下印象,将来需要时再来查阅即可。文章目录已经组织成易于查阅的形式。
函数工具
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;
输入构造函数的类型,输出构造函数的参数的类型。
例子:
class Animal {constructor(name: string, age: number) {
return {
name,
age
};
}
}
type Result = ConstructorParameters<typeof Animal>;
// type Result = [string, number]
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;
输入构造函数的类型,输出实例的类型。
例子:
class Animal {constructor(name: string, age: number) {
return {
name,
age
};
}
}
type Result = InstanceType<typeof Animal>;
// type Result = Animal
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;
输入函数类型,输出函数的参数的类型。
ReturnType
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
输入函数类型,输出函数的返回值的类型。
集合论工具
Exclude
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
从 T 类型中剔除 U 类型。
注意,只能用于从并类型 (Type1|Type2
) 中剔除其中的类型。不支持更加精确的剔除(比如从 string 里剔除 ’1’)。
例子:
type Result = Exclude<"1" | "2", "2" | "3">;
// type Result = "1"
type Result2 = Exclude<string, '1'>;
// type Result2 = string
type Result3 = Exclude<{a: string | number}, {a: number}>;
/*
type Result3 = {a: string | number;}
*/
Extract
/**
* Extract from T those types that are assignable to U
*/
type Extract<T, U> = T extends U ? T : never;
从 T 类型中选择 U 类型。
注意,只能用于从并类型 (Type1|Type2
) 中选择其中的类型。不支持更加精确的选择(比如从 string 里选择 ’1’)。
例子:
type Result1 = Extract<"1" | "2", "2" | "3">;
// type Result1 = "2"
type Result2 = Extract<string, "1">;
// type Result2 = never
type Result3 = Extract<{a: number}, {a: string | number}>;
/*
type Result3 = {a: number;}
*/
type Result4 = Extract<string | number, number | boolean>;
// type Result4 = number
NonNullable
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
从 T 类型中剔除 null 和 undefined。
对象工具
Partial
type Partial<T> = {[P in keyof T]?: T[P];
};
将类型 T 中的属性全部变成 可选 属性。
Required
/**
* Make all properties in T required
*/
type Required<T> = {[P in keyof T]-?: T[P];
};
将类型 T 中的属性全部变成 必选 属性。
Readonly
/**
* Make all properties in T readonly
*/
type Readonly<T> = {readonly [P in keyof T]: T[P];
};
将类型 T 中的属性全部变成 只读 属性。
注意,它仅仅让 对象本身 变成 immutable(不可对属性赋值),但是不会改变属性值的可变性(Immutability)。
类似于浅拷贝与深拷贝的区别。
ReadonlyArray
类型定义比较长。总而言之:
- 不能调用
push
、splice
等修改数组的操作。 - 因为包含属性定义:
readonly [n: number]: T;
,所以不能对数组元素进行赋值修改。
例子:
let arr: ReadonlyArray<string> = ["a", "b"];
arr.push("c"); // error
arr[0] = "c"; // error
注意,它仅仅让 数组本身 变成 immutable(不可对数组项赋值),但是不会改变数组 Item 的可变性(Immutability)。
类似于浅拷贝与深拷贝的区别。
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];
};
从类型 T 中,选出 key 为 K 的属性。
例子:
type Result1 = Pick<{a: number; b: string; c: boolean}, "b" | "c">;
/*
type Result1 = {
b: string;
c: 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>>;
从类型 T 中,过滤 key 为 K 的属性。
例子:
type Result1 = Omit<{a: number; b: string; c: boolean}, "b" | "c">;
/*
type Result1 = {a: number;}
*/
Record
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {[P in K]: T;
};
返回一个对象类型,以 K 为 key,以 T 为 value。
例子:
type Result1 = Record<"a" | "b" | "c", string>;
/*
type Result1 = {
a: string;
b: string;
c: string;
}
*/
type Result2 = Record<"a" | "b" | "c" | number, boolean>;
/*
type Result2 = {[x: number]: boolean;
a: boolean;
b: boolean;
c: boolean;
}
*/
参考资料
- https://github.com/typescript…
- https://github.com/microsoft/…