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

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

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

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

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> 排除 null 和 undefined 条件类型
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 允许字段可选。
  • 结合自定义类型:内置工具类型不够时,可以通过条件类型 + 映射类型组合,写出自己的工具类型。

参考更多资料:

相关推荐
计算机魔术师12 分钟前
半年翻倍!OpenAI再融300亿,估值冲到1.4万亿
前端
研☆香33 分钟前
jQuery + Swiper.js 实现动态渲染轮播图
前端·javascript·jquery
子兮曰1 小时前
Node.js 50个优势场景盘点:一个人单干,为啥我多数时候只用它
前端·后端
IT_陈寒1 小时前
我花3小时debug,就因为JavaScript这个隐式转换坑
前端·人工智能·后端
excel2 小时前
Nuxt 中 useSeoMeta 与 useHead 的区别
前端
竹林8182 小时前
OmniGame 技术白皮书:从零依赖到 WebRTC P2P,重新定义网页小游戏的工程上限
前端·浏览器
ss2732 小时前
AI全栈实战 | 2.1-02 CSS 布局:垂直居中为什么是经典面试题?所有布局在解决什么矛盾
前端·css
律宏阔2 小时前
Flutter Riverpod 3:统一打印 Provider 错误与自动重试日志
前端·flutter
周洲08302 小时前
STM32片内Flash读写深度详解|掉电参数保存、底层原理
linux·前端·stm32
data analyse 4562 小时前
埋点工具的私有化部署成本高吗?
前端·数据分析·github