TypeScript提供了几种有用的工具类型,以便于进行常见的类型转换。这些工具类型在全局可用。
长时间不用,有时候就忘记了, 每次都去官网查看比较麻烦, 特在此记录一份,便于查阅。
Awaited<Type>
用来获取 Promise 返回的类型
看官方的例子
js
type A = Awaited<Promise<string>>;
// 直接得到 string 类型
type A = string
// 支持递归解析
type B = Awaited<Promise<Promise<number>>>;
type B = number
type C = Awaited<boolean | Promise<number>>;
type C = number | boolean
Partial<Type>
将 type 类型的所有属性变为可选, 比较常用。
js
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",
});
Required<Type>
与 Partial
相反, 将 Type 类型的所有属性转为必须有。
js
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 };
// 会报错 缺失了 b 属性
const obj2: Required<Props> = { a: 5 };
Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
// 正确
const obj2: Required<Props> = { a: 5, b: '123' };
Readonly<Type>
将 Type 的所有属性标记为只读属性
js
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
// 报错 属性 title 是只读的 不能修改
todo.title = "Hello";
Record<Keys, Type>
创建一个对象类型, 对象的键是 keys 中的 key, 值是 type 类型 keys 可以是对象属性, 所以只能是 string number symbol 类型
js
const objRecord: Record<6, string> = {
6: 'xxx'
};
官方示例
js
interface CatInfo {
age: number;
breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
Pick<Type, Keys>
从 type 中提取 keys 属性,生成一个新的类型
可以类比 lodash 中的 pick 方法,从一个对象中提取 keys 中的属性,形成一个新对象。
js
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>
与 Pick 相反, 从 Type 类型中移除 keys 中的属性, 剩下的形成一个新的类型。
js
interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
// 将 description 移除 生成一个新的类型
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
createdAt: 1615544252770,
};
// 移除 completed、createdAt 两项生成新的类型
type TodoInfo = Omit<Todo, "completed" | "createdAt">;
const todoInfo: TodoInfo = {
title: "Pick up kids",
description: "Kindergarten closes at 5pm",
};
Exclude<UnionType, ExcludedMembers>
从 UnionType 中 排除 ExcludedMembers 中的类型,生成新的类型。 可以理解为取差集。 注意 ExcludedMembers 描述的是一类 如果有多个符合,都会排除。
js
type T0 = Exclude<"a" | "b" | "c", "a">;
// T0 实际的类型
type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// T1 实际的类型
type T1 = "c"
type T2 = Exclude<string | number | (() => void), Function>;
// T2 实际的类型
type T2 = string | number
// 这里要注意 Function 描述的是一类。 T22 还是 string | number
type T22 = Exclude<string | number | (() => void) | ((a: string) => void), Function>;
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; x: number }
| { kind: "triangle"; x: number; y: number };
type T3 = Exclude<Shape, { kind: "circle" }>
// T3 实际的类型
type T3 = {
kind: "square";
x: number;
} | {
kind: "triangle";
x: number;
y: number;
}
Extract<Type, Union>
从 Type 中取出 Union 中提供的类型且在 Type 中存在的 形成新类型, 其实就是取交集。
js
type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// T0 实际类型
type T0 = "a"
type T1 = Extract<string | number | (() => void), Function>;
// T1 实际类型
type T1 = () => void
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; x: number }
| { kind: "triangle"; x: number; y: number };
type T2 = Extract<Shape, { kind: "circle" }>
// T2 实际类型
type T2 = {
kind: "circle";
radius: number;
}
NonNullable<Type>
从 Type 中排除 unll 和 undefined,生成新类型
js
type T0 = NonNullable<string | number | undefined>;
// T0 实际类型
type T0 = string | number
type T1 = NonNullable<string[] | null | undefined>;
// T1 实际类型
type T1 = string[]
Parameters<Type>
使用函数的参数类型生成元祖类型。
js
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
// T0 实际的类型
type T0 = []
type T1 = Parameters<(s: string) => void>;
// T1 实际的类型
type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
// T2 实际的类型
type T2 = [arg: unknown]
type T3 = Parameters<typeof f1>;
// T3 实际的类型
type T3 = [arg: {
a: number;
b: string;
}]
type T4 = Parameters<any>;
// T4 实际的类型
type T4 = unknown[]
type T5 = Parameters<never>;
// T5 实际的类型
type T5 = never
type T6 = Parameters<string>;
Type 'string' does not satisfy the constraint '(...args: any) => any'.
类型"string"不满足约束"(...args: any) => any"
// T6 实际的类型
type T6 = never
type T7 = Parameters<Function>;
Type 'Function' does not satisfy the constraint '(...args: any) => any'.
Type 'Function' provides no match for the signature '(...args: any): any'.
类型"Function"不满足约束"(...args: any) => any"。
类型"Function"提供的内容与签名"(...args: any): any"不匹配。
// T7 实际的类型
type T7 = never
ConstructorParameters<Type>
使用构造函数的参数生成元祖或者数组类型
js
type T0 = ConstructorParameters<ErrorConstructor>;
// T0 实际的类型
type T0 = [message?: string]
type T1 = ConstructorParameters<FunctionConstructor>;
// T1 实际的类型
type T1 = string[]
type T2 = ConstructorParameters<RegExpConstructor>;
// T2 实际的类型
type T2 = [pattern: string | RegExp, flags?: string]
class C {
constructor(a: number, b: string) {}
}
type T3 = ConstructorParameters<typeof C>;
// T3 实际的类型
type T3 = [a: number, b: string]
type T4 = ConstructorParameters<any>;
// T4 实际的类型
type T4 = unknown[]
type T5 = ConstructorParameters<Function>;
Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.
Type 'Function' provides no match for the signature 'new (...args: any): any'.
类型"Function"不满足约束"abstract new (...args: any) => any"。
类型"Function"提供的内容与签名"new (...args: any): any"不匹配。
// T5 实际的类型
type T5 = never