一文掌握 TypeScript 工具类型:Record、Partial、Omit、Pick 等实战用法

一文搞懂 TypeScript 常用泛型工具类型(Record、Partial、Omit、Pick 等)

TypeScript 内置了一批 泛型工具类型 ,比如 RecordPartialOmitPick 等,它们能基于已有类型快速生成新类型,避免重复定义,让类型既安全又灵活。

如果你停留在只会"用",却不太理解 为什么会出现原理是什么最佳实践如何选型 。本文就带你从 痛点 → 工具类型 → 实战 → 原理,一次性搞透。

1. 为什么会出现?

早期 TypeScript 开发的痛点:

  • 相似的类型要重复写多份
  • 为了适配不同场景,需要频繁复制粘贴类型定义
  • 一旦源类型变动,所有相关类型都要手动更新

泛型工具类型就是为了解决这些问题:

  • 减少重复:用组合和派生代替重复声明
  • 提升安全:编译器帮你检查类型错误
  • 更灵活:业务变动时派生类型自动适配

2. 常用工具类型列表

工具类型 作用 简述原理
Record<K, T> 将键集合 K 映射到类型 T 映射类型批量生成属性
Partial<T> 将所有属性设为可选 ? 修饰符映射
Omit<T, K> T 排除 K 属性 Pick + Exclude
Pick<T, K> 只保留 K 指定属性 映射类型选择
Required<T> 将所有属性设为必填 去掉 ? 修饰符
Readonly<T> 将所有属性设为只读 readonly 修饰符映射
Exclude<T, U> 从联合类型 T 排除类型 U 条件类型
Extract<T, U> 从联合类型 T 提取 U 类型 条件类型
NonNullable<T> 排除 nullundefined 条件类型
ReturnType<F> 获取函数返回值类型 infer 推导
InstanceType<C> 获取构造函数实例类型 infer 推导

3. 使用场景与原理

3.1 Record:权限表

ts 复制代码
type Role = 'admin' | 'editor' | 'viewer';
type Permission = 'read' | 'write' | 'delete';

const rolePermissions: Record<Role, Permission[]> = {
  admin: ['read', 'write', 'delete'],
  editor: ['read', 'write'],
  viewer: ['read']
};

原理Record<K, T> 本质就是"用 K 的所有键生成一组属性":

ts 复制代码
type Record<K extends keyof any, T> = {
  [P in K]: T;
}

3.2 Partial:更新用户信息

ts 复制代码
interface UserProfile {
  id: number;
  name: string;
  email: string;
}
function updateUser(id: number, updates: Partial<UserProfile>) {
  // ...
}

updateUser(1, { email: 'new@example.com' });

原理 :通过映射类型给所有属性加上 ?

ts 复制代码
type Partial<T> = {
  [P in keyof T]?: T[P];
}

3.3 Omit:去除敏感字段

ts 复制代码
interface User {
  id: number;
  name: string;
  password: string
}
type SafeUser = Omit<User, 'password'>;

原理 :其实就是 Pick + Exclude 的组合:

ts 复制代码
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

3.4 Pick:只要部分字段

ts 复制代码
type UserNameEmail = Pick<UserProfile, 'name' | 'email'>;

原理 :只保留 K 中的键:

ts 复制代码
type Pick<T, K extends keyof any> = {
  [P in K]: T[P]
}

3.5 Required:接口必填化

ts 复制代码
type StrictUser = Required<Partial<UserProfile>>;

3.6 Readonly:让属性只读

ts 复制代码
const config: Readonly<{ apiUrl: string }> = {
  apiUrl: 'https://api.example.com'
};
config.apiUrl = '' // 报错

3.7 Exclude & Extract:联合类型过滤

ts 复制代码
type T = 'a' | 'b' | 'c';

type WithoutB = Exclude<T, 'b'>; // 'a' | 'c'
type OnlyB = Extract<T, 'b'>; // 'b'

对比:

  • Pick/Omit 好比一个 对象裁剪器 :我有一张"用户表单",我要么只留下 name/email(Pick),要么去掉 password(Omit)。
  • Exclude/Extract 好比一个 集合过滤器 :我有一个集合 {'a','b','c'},我去掉 b(Exclude)或只要 b(Extract)。

3.8 NonNullable:去掉 null/undefined

ts 复制代码
type Value = string | null | undefined;
type SafeValue = NonNullable<Value>; // string

3.9 ReturnType & InstanceType:类型推导

ts 复制代码
function getUser() {
  return { id: 1, name: 'Alice' };
}
type UserReturn = ReturnType<typeof getUser>; 
// { id: number; name: string; }

class Person { name = 'Bob'; }
type PersonInstance = InstanceType<typeof Person>; 
// Person

4. 工具类型的实现思路

常见实现方式有三类:

  1. 映射类型Record / Partial / Pick / Omit / Readonly / Required

  2. 条件类型Exclude / Extract / NonNullable

  3. infer 推导ReturnType / InstanceType

5. 最佳实践与注意事项

  • 避免过度嵌套Partial<Required<Pick<...>>> 会让类型难以阅读,尽量保持扁平。
  • 业务分层使用 :比如 DTO 层用 Omit 去掉数据库 ID,前端表单用 Partial 允许字段可选。
  • 结合自定义类型:内置工具类型不够时,可以通过条件类型 + 映射类型组合,写出自己的工具类型。

参考更多资料:

相关推荐
mldong1 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排2 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰4 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马7 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒7 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端