导入
实用类型:Pick、Omit、Partial 和 Required
掌握最有用的内置工具类型,编写更简洁、更安全且更易维护的 TypeScript 代码。
1type FullUser = { 2 id: string; 3 name: string; 4 email: string; 5 passwordHash: string; 6}; 7 8type PublicUser = Pick<FullUser, "id" | "name">; 9 10const view: PublicUser = { 11 id: "u123", 12 name: "Zara", 13}; 14 15console.log(view);
1type Config = { 2 apiKey: string; 3 endpoint: string; 4 retries: number; 5}; 6 7type ClientConfig = Omit<Config, "apiKey">; 8 9const safe: ClientConfig = { 10 endpoint: "/api", 11 retries: 2, 12}; 13 14console.log(safe);
1type User = { 2 id: string; 3 name: string; 4 email: string; 5}; 6 7type UpdatePayload = Partial<Omit<User, "id">>; 8 9const update: UpdatePayload = { 10 name: "Tasha", 11}; 12 13console.log(update);
1type FormDraft = { 2 name?: string; 3 email?: string; 4}; 5 6type FinalForm = Required<FormDraft>; 7 8const form: FinalForm = { 9 name: "Alok", 10 email: "a@example.com", 11}; 12 13console.log(form);
1type Product = { 2 sku: string; 3 name: string; 4 price: number; 5 tags?: string[]; 6}; 7 8type ProductDraftMap = Record<string, Partial<Omit<Product, "sku">>>; 9 10const drafts: ProductDraftMap = { 11 p1: { name: "Shirt" }, 12 p2: { price: 19.99, tags: ["sale"] }, 13}; 14 15console.log(drafts);
1type Todo = { 2 id: number; 3 title: string; 4 completed: boolean; 5 tags?: string[]; 6}; 7 8// 定义 DraftTodo 9// 定义 SanitizedTodo 10// 定义 FinalizedTodo 11 12// 测试代码 13 14// ✅ DraftTodo – title 必填,其余可选 15const draft1: DraftTodo = { title: "开始项目" }; 16const draft2: DraftTodo = { title: "买杂货", completed: false }; 17 18console.log("草稿:", draft1, draft2); 19// const draftError: DraftTodo = { completed: true }; // ❌ 错误:缺少 title 20 21// ✅ SanitizedTodo – 不允许包含 id 22const sanitized: SanitizedTodo = { 23 title: "发布博客文章", 24 completed: true, 25 tags: ["写作"], 26}; 27 28console.log("清理后:", sanitized); 29// const sanitizedError: SanitizedTodo = { id: 1, title: "出错了", completed: true }; // ❌ 错误:不应存在 id 30 31// ✅ FinalizedTodo – 所有字段必填,包括 tags 32const final: FinalizedTodo = { 33 id: 1, 34 title: "提交 PR", 35 completed: true, 36 tags: ["代码", "评审"], 37}; 38 39console.log("最终版:", final); 40// const finalError: FinalizedTodo = { id: 2, title: "差不多了", completed: true }; // ❌ 错误:缺少 tags
提示
- 使用
Omit<T, K>从类型中移除指定字段。 - 使用
Partial<T>将类型的所有字段变为可选。 - 使用
Pick<T, K>提取所需字段并确保其存在。 - 使用
&操作符合并类型,精确控制哪些字段是必需的、哪些是可选的。
解决方案:组合工具类型以建模 Todo 的各种变体
1type Todo = { 2 id: number; 3 title: string; 4 completed: boolean; 5 tags?: string[]; 6}; 7 8type DraftTodo = Partial<Omit<Todo, "title">> & Pick<Todo, "title">; 9type SanitizedTodo = Omit<Todo, "id">; 10type FinalizedTodo = Required<Todo>; 11 12// 测试代码 13 14// ✅ DraftTodo – title 必填,其余可选 15const draft1: DraftTodo = { title: "开始项目" }; 16const draft2: DraftTodo = { title: "买杂货", completed: false }; 17 18console.log("草稿:", draft1, draft2); 19// const draftError: DraftTodo = { completed: true }; // ❌ 错误:缺少 title 20 21// ✅ SanitizedTodo – 不允许包含 id 22const sanitized: SanitizedTodo = { 23 title: "发布博客文章", 24 completed: true, 25 tags: ["写作"], 26}; 27 28console.log("清理后:", sanitized); 29// const sanitizedError: SanitizedTodo = { id: 1, title: "出错了", completed: true }; // ❌ 错误:不应存在 id 30 31// ✅ FinalizedTodo – 所有字段必填,包括 tags 32const final: FinalizedTodo = { 33 id: 1, 34 title: "提交 PR", 35 completed: true, 36 tags: ["代码", "评审"], 37}; 38 39console.log("最终版:", final); 40// const finalError: FinalizedTodo = { id: 2, title: "差不多了", completed: true }; // ❌ 错误:缺少 tags
说明:
-
第 8 行:
DraftTodo组合多个工具类型,使得除title外所有字段都可选:Omit<Todo, "title">移除title字段;Partial<...>将剩余字段设为可选;Pick<Todo, "title">重新引入title并设为必填;- 使用
&将两部分合并,得到仅title必填的类型。
-
第 9 行:
SanitizedTodo使用Omit移除内部使用的id字段,用于安全地对外暴露数据。 -
第 10 行:
FinalizedTodo使用Required确保所有字段(包括原本可选的tags)都必须提供。