本篇翻译整理自 TypeScript Handbook 中 「utility-types」 章节。
TypeScript 提供了几种工具类型来帮助我们进行常见的类型转换
Partial<Type>
将Type的所有属性都设置为可选的类型。
interface Todo {
title: string;
description: string;
}
// 工具类型定义的是类型,所以需要使用type来进行声明
type PartialTodo = Partial<Todo>
/*
type PartialTodo = {
title?: string | undefined;
description?: string | undefined;
}
*/
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>
Type的所有属性都设置为必填项
interface Props {
a?: number;
b?: string;
}
const obj: Props = { a: 5 };
const obj2: Required<Props> = { a: 5 };
// Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
Readonly<Type>
Type的所有属性都设置为只读
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
todo.title = "Hello";
// Cannot assign to 'title' because it is a read-only property.
Record<Keys, Type>
以keys中的每一项为key,vakue为Type构建一个新对象
此工具类型可用于将一种类型的属性映射到另一种类型。
type CatName = "Klaus" | 'Steven' | 'Alex';
const cats: Record<CatName, { age: number }> = {
Klaus: { age: 10},
Steven: { age: 5},
Alex: { age: 5 }
}
interface CatInfo {
age: number;
breed: string;
}
const s1 = Symbol()
// 因为CatName会作为对象的key使用
// 所以key可以取值的类型有 string | number | symbol
type CatName = "miffy" | 111 | typeof s1;
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
111: { age: 5, breed: "Maine Coon" },
[s1]: { age: 5, breed: "Maine Coon" }
}
Pick<Type, Keys>
从Type中提起Keys中对应的value组成一个新的类型
interface Todo {
title: string;
description: string;
completed: boolean;
}
// 设置的key值必须是Todo接口上存在的值
type TodoPreview = Pick<Todo, "title" | "completed">
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
Omit<Type, Keys>
在Type(此时的Type的类型一般是对象)中移除对应的Keys
interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
type TodoPreview = Omit<Todo, "description">
const todo: TodoPreview = {
title: "Clean room",
completed: false,
createdAt: 1615544252770,
}
Exclude<Type, ExcludedUnion>
从一个Type(此时的Type的类型一般为联合类型)中移除对应的类型
type T0 = Exclude<"a" | "b" | "c", "a">;
// type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// type T1 = "c"
type T2 = Exclude<string | number | (() => void), Function>;
// type T2 = string | number
Extract<Type, Union>
从Type中提取符合Union的类型
type T0 = Extract<"a" | "b" | "c", "a" | "f">;
// type T0 = "a"
type T1 = Extract<string | number | (() => void), Function>;
// type T1 = () => void
NonNullable<Type>
通过排除null和undefined来自构造一个类型Type
type T0 = NonNullable<string | number | undefined>;
// type T0 = string | number
type T1 = NonNullable<string[] | null | undefined>;
// type T1 = string[]
Parameters<Type>
Type为函数时候,提取函数的参数组成一个新的元组
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
// type T0 = []
type T1 = Parameters<(s: string) => void>;
// type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
// type T2 = [arg: unknown]
type T3 = Parameters<typeof f1>;
/*
type T3 = [arg: {
a: number;
b: string;
}]
*/
type T4 = Parameters<any>;
// type T4 = unknown[]
type T5 = Parameters<never>;
// type T5 = never
type T6 = Parameters<string>; // error
type T7 = Parameters<Function>; // error
ConstructorParameters<Type>
Type为构造函数
通过构造函数的参数组成元组或数组类型
如果Type不是函数的类型,会返回never
// ErrorConstructor, FunctionConstructor都是TS内置的构造函数的类型
type T0 = ConstructorParameters<ErrorConstructor>;
type T1 = ConstructorParameters<FunctionConstructor>;
type T2 = ConstructorParameters<RegExpConstructor>;
type T3 = ConstructorParameters<any>;
ReturnType<Type>
Type为函数,获取函数返回值的类型
type T0 = ReturnType<() => string>;
// type T0 = string
type T1 = ReturnType<(s: string) => void>;
// type T1 = void
type T2 = ReturnType<<T>() => T>;
// type T2 = unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
// type T3 = number[]
InstanceType<Type>
Type为类,获取Type的实例类型
class C {
x = 0;
y = 0;
}
type T0 = InstanceType<typeof C>;
// type T0 = C
type T1 = InstanceType<any>;
// type T1 = any
type T2 = InstanceType<never>;
// type T2 = never
ThisParameterType<Type>
Type为函数,获取函数调用时候的this参数的类型
function toHex(this: Number) {
return this.toString(16);
}
// type n = number
function numberToString(n: ThisParameterType<typeof toHex>) {
return toHex.apply(n);
}
function toHex() {
return 16
}
// 如果函数没有this参数,那么类型就是unknown
// type n = unknown
function numberToString(n: ThisParameterType<typeof toHex>) {
return toHex.apply(n);
}
OmitThisParameter<Type>
从Type中剔除this参数
function toHex(this: Number) {
return this.toString(16);
}
const fiveToHex: OmitThisParameter<typeof toHex> = toHex.bind(5);
// const fiveToHex: () => string
ThisType<Type>
用于指定函数调用的时候,函数内部this的类型
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);
内置字符串操作类型
内置字符串操作类型的使用可以在模板字面量类型中查看