- Published on
写TS效率大提升,TypeScript中常用内置工具类型Omit、Pick、Partial、Required、Readonly、Exclude 、Extract
- Authors

- 作者
- kai
目录

写TS效率大提升:TypeScript中常用内置工具类型详解
TypeScript作为JavaScript的超集,提供了强大的类型系统来增强代码的可维护性和开发体验。其中,TypeScript内置的工具类型(Utility Types)是提升开发效率的重要特性。本文将详细介绍Omit、Pick、Partial、Required、Readonly、Exclude、Extract等常用工具类型的使用方法和应用场景。
什么是TypeScript内置工具类型
TypeScript内置工具类型是TypeScript提供的一组预定义的泛型类型,用于对现有类型进行转换和操作。这些工具类型可以帮助我们更轻松地创建新的类型,避免重复编写复杂的类型定义。
常用内置工具类型详解
1. Partial<T>
Partial<T>将类型T的所有属性变为可选。
interface User {
id: number;
name: string;
email: string;
}
// 使用Partial创建可选属性的类型
type PartialUser = Partial{'<User>'};
// 等价于:
// interface PartialUser {
// id?: number;
// name?: string;
// email?: string;
// }
// 使用示例
const updateUser = (user: User, updates: PartialUser) => {
return { ...user, ...updates };
};
const user: User = { id: 1, name: "张三", email: "zhangsan@example.com" };
const updatedUser = updateUser(user, { name: "李四" }); // 只更新name属性
2. Required<T>
Required<T>将类型T的所有属性变为必需。
interface UserOptions {
id?: number;
name?: string;
email?: string;
}
// 使用Required创建所有属性必需的类型
type RequiredUser = Required{'<UserOptions>'};
// 等价于:
// interface RequiredUser {
// id: number;
// name: string;
// email: string;
// }
// 使用示例
const createUser = (options: RequiredUser) => {
// 所有属性都是必需的
return {
id: options.id,
name: options.name,
email: options.email
};
};
3. Readonly<T>
Readonly<T>将类型T的所有属性变为只读。
interface Config {
apiUrl: string;
timeout: number;
}
// 使用Readonly创建只读类型
type ReadonlyConfig = Readonly{'<Config>'};
// 等价于:
// interface ReadonlyConfig {
// readonly apiUrl: string;
// readonly timeout: number;
// }
// 使用示例
const config: ReadonlyConfig = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// config.apiUrl = "new url"; // 编译错误:无法分配到 "apiUrl" ,因为它是只读属性
4. Pick<T, K>
Pick<T, K>从类型T中选择指定的属性K,构造新类型。
interface User {
id: number;
name: string;
email: string;
password: string;
}
// 使用Pick选择部分属性
type UserPublicInfo = Pick{'<User, "id" | "name" | "email">'};
// 等价于:
// interface UserPublicInfo {
// id: number;
// name: string;
// email: string;
// }
// 使用示例
const getUserPublicInfo = (user: User): UserPublicInfo => {
const { password, ...publicInfo } = user;
return publicInfo;
};
5. Omit<T, K>
Omit<T, K>从类型T中排除指定的属性K,构造新类型。
interface User {
id: number;
name: string;
email: string;
password: string;
}
// 使用Omit排除部分属性
type UserWithoutPassword = Omit{'<User, "password">'};
// 等价于:
// interface UserWithoutPassword {
// id: number;
// name: string;
// email: string;
// }
// 使用示例
const sendUserInfo = (user: UserWithoutPassword) => {
// 不包含密码信息
console.log("用户信息: " + user.name + ", " + user.email);
};
6. Record<K, T>
Record<K, T>构造一个对象类型,其属性键为K,属性值为T。
// 使用Record创建字典类型
type UserRole = "admin" | "user" | "guest";
type Permission = {
read: boolean;
write: boolean;
};
type RolePermissions = Record{'<UserRole, Permission>'};
// 等价于:
// interface RolePermissions {
// admin: Permission;
// user: Permission;
// guest: Permission;
// }
// 使用示例
const permissions: RolePermissions = {
admin: { read: true, write: true },
user: { read: true, write: false },
guest: { read: false, write: false }
};
7. Exclude<T, U>
Exclude<T, U>从类型T中排除可以赋值给类型U的类型。
type Status = "pending" | "fulfilled" | "rejected";
type SuccessStatus = Exclude{'<Status, "rejected">'};
// SuccessStatus 等价于 "pending" | "fulfilled"
// 使用示例
const handleSuccess = (status: SuccessStatus) => {
// 只处理成功状态
console.log("成功状态: " + status);
};
8. Extract<T, U>
Extract<T, U>从类型T中提取可以赋值给类型U的类型。
type Status = "pending" | "fulfilled" | "rejected";
type ErrorStatus = Extract{'<Status, "rejected">'};
// ErrorStatus 等价于 "rejected"
// 使用示例
const handleError = (status: ErrorStatus) => {
// 只处理错误状态
console.log("错误状态: " + status);
};
组合使用示例
在实际开发中,我们经常需要组合使用这些工具类型来满足复杂的需求:
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
updatedAt: Date;
}
// 创建用于创建用户的类型(排除id和时间戳)
type CreateUserInput = Omit{'<User, "id" | "createdAt" | "updatedAt">'};
// 创建用于更新用户的类型(所有属性可选,排除密码)
type UpdateUserInput = Partial{'<Omit<User, "password">>'};
// 创建用户列表项类型(只包含基本信息)
type UserListItem = Pick{'<User, "id" | "name" | "email">'};
// 使用示例
const createUser = (input: CreateUserInput): User => {
return {
id: Math.random(),
...input,
createdAt: new Date(),
updatedAt: new Date()
};
};
const updateUser = (id: number, updates: UpdateUserInput): User | null => {
// 更新逻辑
return null;
};
const listUsers = (): UserListItem[] => {
// 返回用户列表
return [];
};
最佳实践
- 合理使用:根据实际需求选择合适的工具类型,避免过度复杂化
- 命名规范:为组合使用的工具类型定义有意义的类型别名
- 文档注释:为复杂的类型定义添加注释说明
- 类型复用:将常用的类型组合定义为可复用的类型别名
总结
TypeScript的内置工具类型为我们提供了强大的类型操作能力,可以显著提升开发效率和代码质量。掌握这些工具类型的使用方法,能够帮助我们:
- 减少重复的类型定义
- 提高代码的可维护性
- 增强类型安全性
- 简化复杂类型的创建
在日常开发中,合理运用这些工具类型,可以让我们的TypeScript代码更加简洁、优雅和健壮。
