TypeScript 实用类型深度解析:Partial、Pick、Record 的妙用

需求背景:在后台系统的用户管理模块中,我们常遇到这样的场景:修改用户资料时只需要传部分字段,展示用户列表时要隐藏敏感信息,快速查找用户需要ID索引等等,这些业务需求都可以通过 TypeScript 的实用类型优雅解决。

文章目录

  • 一、`Partial` : 构建灵活更新模型
  • 二、`Pick`:精准数据裁剪术
  • 三、`Record`:构建类型安全字典
  • 四、实用类型全家桶
  • 五、类型组合的化学效应
  • 六、最佳实践指南

一、Partial : 构建灵活更新模型

实现原理

type MyPartial<T> = {
	[P in keyof T]?: T[P];
}

通过映射类型遍历所有属性,为每个属性添加 ? 修饰符

典型场景:

// 用户更新表单类型
type UpdateUserForm = Partial<User>;

// 使用示例
const updateData: UpdateUserForm = {
	name: '',
	email: '',
}

优势:

  • 避免定义重复的 DTO 类型
  • 防止误传未修改的字段
  • 与后端 PATCH 接口完美契合

二、Pick:精准数据裁剪术

实现原理:

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})
`; }

延伸技巧:

// 组合使用实现高级类型
type AuditLog = Pick<User, 'id'> & {
	action: string;
	timestamp: Date;
}

三、Record:构建类型安全字典

实现原理:

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: "[email protected]" },
	2: { id: 2, name: "Bob", email: "[email protected]" }
};

// 快速查找用户
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 :反向Pick

type SensitiveUser = Omit<User, 'password' | 'token'>;

2.Readonly :构建不可变对象

const defaultConfig: Readonly<Config> = { /*...*/ };

3.Required :去除所有可选修饰符

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];
};

六、最佳实践指南

  1. 渐进式类型:从 any 开始逐步替换
  2. 类型文档化:重要类型添加注释
/**
 * 用户核心字段(不含敏感信息)
 * @property id - 用户唯一标识
 * @property name - 显示名称
 */
type PublicUser = Pick<User, 'id' | 'name'>;

你可能感兴趣的:(typescript,javascript,前端)