内置工具类型的作用:Partial<T>、Required<T> 和 Readonly<T>
TypeScript 提供了许多内置的工具类型(Utility Types),用于在现有类型的基础上进行转换,从而简化类型定义。
你提到的 Partial<T>、Required<T> 和 Readonly<T> 是最常用的三个,它们的核心作用都是基于现有类型 T 创建一个新的类型,但对属性的修饰符做了不同的处理。
以下是详细的解释和代码示例:
1. Partial<T> (部分/可选)
作用:
将类型 T 中的所有属性都变为 可选的(Optional)(即加上 ? 修饰符)。
场景:
当你需要创建一个对象,但只包含原类型的一部分属性时非常有用。常见于更新数据(Patch)或配置项合并的场景。
示例:
interface User {
id: number;
name: string;
email: string;
}
// 场景:更新用户信息,只修改 name,不修改 email 和 id
function updateUser(id: number, fieldsToUpdate: Partial<User>) {
// ... 数据库更新逻辑
}
// ✅ 合法:只传了 name
updateUser(1, { name: "Alice" });
// ✅ 合法:传了 name 和 email
updateUser(1, { name: "Bob", email: "bob@example.com" });
// ❌ 报错:age 不存在于 User 中
// updateUser(1, { age: 18 });
原理简述:
相当于把 { name: string } 变成了 { name?: string }。
2. Required<T> (必填)
作用:
将类型 T 中的所有属性都变为 必填的(Required)(即移除 ? 修饰符)。它是 Partial 的反义词。
场景:
当你定义了一个包含许多可选属性的接口(例如配置对象),但在代码的某个处理阶段(例如合并了默认值之后),你需要确保所有属性都必须存在值,不再是 undefined。
示例:
interface Config {
timeout?: number;
retries?: number;
theme?: string;
}
// 假设有一个包含默认值的对象
const defaultConfig: Required<Config> = {
timeout: 1000,
retries: 3,
theme: 'dark'
};
// 用户只传了部分配置
const userConfig: Config = { theme: 'light' };
// 合并配置:结果肯定包含所有属性
const finalConfig: Required<Config> = { ...defaultConfig, ...userConfig };
// ✅ 此时访问 finalConfig.timeout 不需要判空,因为它一定是 number
console.log(finalConfig.timeout);
// ❌ 如果尝试定义一个缺省属性的 Required 对象会报错
// const errorConfig: Required<Config> = { timeout: 5000 }; // 报错:缺少 retries 和 theme
原理简述:
相当于把 { timeout?: number } 变成了 { timeout: number }。
3. Readonly<T> (只读)
作用:
将类型 T 中的所有属性都变为 只读的(Readonly)。
场景:
用于防止对象被修改。常见于 React 的 Props、Redux 的 State 或者任何需要保证数据不可变(Immutability)的函数式编程场景。
示例:
interface Todo {
title: string;
}
const myTodo: Readonly<Todo> = {
title: "学习 TypeScript"
};
// ✅ 读取是允许的
console.log(myTodo.title);
// ❌ 修改会报错
// myTodo.title = "学习 Vue"; // Error: Cannot assign to 'title' because it is a read-only property.
原理简述:
相当于把 { title: string } 变成了 { readonly title: string }。
总结对比
假设有一个原始类型:
interface Person {
name: string;
age?: number; // 注意这里原本是可选的
}
| 工具类型 | 转换后的效果 | 解释 |
|---|---|---|
Partial<Person> |
{ name?: string; age?: number; } |
所有属性变可选。 |
Required<Person> |
{ name: string; age: number; } |
所有属性变必填(age 的 ? 被移除了)。 |
Readonly<Person> |
{ readonly name: string; readonly age?: number; } |
所有属性变只读(不可重新赋值)。 |
这三个工具类型是 TypeScript 中最基础也是最高频使用的工具,掌握它们能大大提高类型定义的灵活性。