TypeScript 提供了许多内置的工具类型,这些工具类型可以帮助我们更轻松地定义和操作类
TypeScript提供的内置工具类型如下:
Partial
将一个对象类型的所有属性变为可选。
下面是一个示例,使用 Partial
实现一个可以部分更新用户信息的函数:
interface User {
name: string;
age: number;
email: string;
}
const updateUser = (user: User, updates: Partial<User>): User => {
return {
...user, ...updates };
}
const user: User = {
name: 'Alice', age: 30, email: 'alice@example.com' };
const updatedUser = updateUser(user, {
name: 'Bob' });
在上面的示例中,我们定义了一个 User
接口,它有三个属性:name
、age
和 email
。然后我们定义了一个 updateUser 函数,该函数接受一个 User
对象和一个部分用户对象(即,它可以包含 User
对象的部分属性)。该函数返回一个新的 User
对象,其中包含原始 User
对象的所有属性和部分用户对象中的属性。
为了使 updateUser
函数能够接受部分用户对象,我们使用了 Partial<User>
类型。这个类型会将 User 对象中的所有属性变为可选。这意味着我们可以只传递 User
对象中的一部分属性到 updateUser
函数中,而不需要传递所有属性。
下面是一个简单的 TypeScript 实现 Partial 的示例。
type Partial<T> = {
[P in keyof T]?: T[P];
};
在这个实现中,我们使用了映射对象类型,它会遍历 T
类型的所有属性,并将它们变为可选属性。由于 ?
符号将属性变为可选,因此我们只需要将属性的类型设置为原始属性的类型即可。
需要注意的是,我们使用 keyof T
获取 T
类型的所有属性名称。然后,我们使用 P in keyof T
循环遍历这些属性,并将它们变为可选属性。最后,我们使用 T[P]
获取原始属性的类型,并将其设置为可选属性的类型。
Required
将一个对象类型中的所有属性变为必需的。
下面是一个示例,使用 Required
实现一个可以创建必填订单的函数:
interface Order {
id?: number;
customerId?: number;
date?: Date;
amount?: number;
}
const createOrder = (order: Required<Order>): void => {
// ...
}
const order: Order = {
customerId: 123, amount: 100 };
createOrder(order); // Error: Property 'id' is missing
在上面的示例中,我们定义了一个 Order
接口,它有四个属性:id
、customerId
、date
和 amount
,其中所有属性都是可选的。然后我们定义了一个 createOrder
函数,该函数接受一个必填订单对象,并在函数内部进行一些操作。
在函数调用中,我们只传递了 Order
对象中的一部分属性,即 customerId
和 amount
。由于 Order
对象的其他属性是可选的,因此 TypeScript 编译器会报错,提示缺少 id 属性。
为了将 Order
对象中的所有属性变为必需属性,我们可以使用 Required<Order>
类型。这个类型会将 Order
对象中的所有属性变为必需属性。这意味着我们必须在创建 Order
对象时填写所有属性。
下面是一个简单的 Typescript 实现 Required 的示例:
type Required<T> = {
[P in keyof T]-?: T[P];
};
在这个实现中,我们使用了映射对象类型,它会遍历 T
类型的所有属性,并将它们变为必需属性。由于 -
符号将属性变为必需属性,因此我们只需要将属性的类型设置为原始属性的类型即可。
需要注意的是,我们使用 keyof T
获取 T
类型的所有属性名称。然后,我们使用P in keyof T
循环遍历这些属性,并将它们变为必需属性。最后,我们使用 T[P]
获取原始属性的类型,并将其设置为必需属性的类型。
Readonly
将给定类型的所有属性设置为只读。
基本语法如下:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
其中,T
是要设置为只读的类型。下面是一些使用 Readonly
的示例和它们的实现。
示例 1:将对象的所有属性设置为只读。
interface Person {
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
const person: ReadonlyPerson = {
name: "Alice",
age: 30,
};
person.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property.
person.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.
在上面的示例中,我们使用 Readonly<Person>
将 Person
接口的所有属性设置为只读,并生成了一个 ReadonlyPerson
类型。然后,我们定义了一个包含 ReadonlyPerson
类型的对象 person
,并尝试修改它的属性,但是会报错,因为属性是只读的。
示例 2:将对象的部分属性设置为只读。
interface Person {
name: string;
age: number;
address: {
city: string;
street: string;
};
}
type ReadonlyPerson = {
readonly name: string;
age: number;
readonly address: {
readonly city: string;