TypeScript 实用类型深度解析:Partial、Pick、Record 的妙用
需求背景:在后台系统的用户管理模块中,我们常遇到这样的场景:修改用户资料时只需要传部分字段,展示用户列表时要隐藏敏感信息,快速查找用户需要ID索引等等,这些业务需求都可以通过 TypeScript 的实用类型优雅解决。
文章目录
- 一、`Partial<T>` : 构建灵活更新模型
- 二、`Pick<T,K>`:精准数据裁剪术
- 三、`Record<K,T>`:构建类型安全字典
- 四、实用类型全家桶
- 五、类型组合的化学效应
- 六、最佳实践指南
一、Partial<T>
: 构建灵活更新模型
实现原理
type MyPartial<T> = {[P in keyof T]?: T[P];
}
通过映射类型遍历所有属性,为每个属性添加 ?
修饰符
典型场景:
// 用户更新表单类型
type UpdateUserForm = Partial<User>;// 使用示例
const updateData: UpdateUserForm = {name: '',email: '',
}
优势:
- 避免定义重复的 DTO 类型
- 防止误传未修改的字段
- 与后端 PATCH 接口完美契合
二、Pick<T,K>
:精准数据裁剪术
实现原理:
type MyPick<T, K extends keyof T> = {[P in K] : T[P];
};
通过K限定要保留的属性键集合
实战应用
// 安全返回给前端的基础信息
type PublicUserProfile = Pick<User, 'id' | 'name'>;// 生成用户名片数据
const renderUserCard = (user: PublicUserProfile) => {return `<div>${user.name} (#${user.id})</div>`;
}
延伸技巧:
// 组合使用实现高级类型
type AuditLog = Pick<User, 'id'> & {action: string;timestamp: Date;
}
三、Record<K,T>
:构建类型安全字典
实现原理:
type MyRecord<K extends keyof any, T> = {[P in K]: T;
}
约束键的类型必须是有效索引类型(string | number | symbol)
典型应用:
// 用户ID到用户对象的映射
const userCache: Record<number, User> = {1: { id: 1, name: "Alice", email: "alice@example.com" },2: { id: 2, name: "Bob", email: "bob@example.com" }
};// 快速查找用户
const getUser = (id: number) => userCache[id]
高级用法:
// 配置系统多语言字典
type Locale = 'en' | 'zh';
type Messages = Record<Locale, Record<string, string>>;const messages: Messages = {en: { welcome: "Welcome", logout: "Logout" },zh: { welcome: "欢迎", logout: "退出登录" }
};
四、实用类型全家桶
1.Omit<T,K>
:反向Pick
type SensitiveUser = Omit<User, 'password' | 'token'>;
2.Readonly<T>
:构建不可变对象
const defaultConfig: Readonly<Config> = { /*...*/ };
3.Required<T>
:去除所有可选修饰符
type StrictUser = Required<User>; // phone变为必填
五、类型组合的化学效应
// 分页响应通用模板
type PaginatedResponse<T> = {data: T[];total: number;
} & Record<string, unknown>;// 用户搜索过滤器
type UserFilter = Partial<Pick<User, 'name' | 'email'>> & {createTime?: [Date, Date];
};
六、最佳实践指南
- 渐进式类型:从 any 开始逐步替换
- 类型文档化:重要类型添加注释
/*** 用户核心字段(不含敏感信息)* @property id - 用户唯一标识* @property name - 显示名称*/
type PublicUser = Pick<User, 'id' | 'name'>;