编程前端开发者

TypeScript中的Pick是如何工作的,这个实用程序类型有什么用处,它与Omit有什么区别?

用 Hintsage AI 助手通过面试

回答。

实用程序类型Pick<T, K>是为了解决从现有类型或接口选择性复制部分字段的问题而添加到TypeScript中的。

问题背景

在开发过程中,经常会重复使用带有轻微变化的数据结构。在出现Pick之前,开发者不得不手动复制所需字段来创建新的接口,这造成了代码重复和在后续修改原始结构时的错误。

问题

需要对函数的输入或输出数据进行类型化,仅使用大型接口中的部分字段,以避免冗余,并最大限度地具体化契约。

解决方案

Pick解决了根据键K提取类型T的属性子集的问题:

type Pick<T, K extends keyof T> = { [P in K]: T[P] };

示例:

interface User { id: number; name: string; email: string; } type Credentials = Pick<User, 'email' | 'name'>; const creds: Credentials = { email: "user@example.com", name: "User Name", };

关键特性:

  • 创建一个仅包含所需键的新类型;
  • 对于类型化select查询、表单输出非常方便;
  • 最小化手动代码和重构时的错误数量。

具有陷阱的问题。

Pick与Omit有什么区别?

Pick仅选择指定的类型字段;Omit则相反,从结构中排除它们。

type PartialUser = Omit<User, 'id'>; // 除id外的所有字段

可以通过Pick选择不存在的属性吗?

不可以,K键必须是原始类型的键,否则会导致编译错误。

Pick可以影响可选性或readonly字段吗?

如果原始类型中有修饰符(optional,readonly),Pick会保留这些修饰符,仅将它们复制到新的类型中。

常见错误和反模式

  • 在Pick中显式用字符串("id, name")列举,而不是键数组,这会导致编译错误。
  • 选择不存在的字段或错误的自动生成键。
  • 在需要排除或修改属性的场合使用Pick——这时应该使用Omit、Partial、Required。

生活中的例子

负面案例

在处理数据输入表单时,开发者手动描述了自己的类型,遗忘了User中新增的强制属性。在更新接口后,表单崩溃了。

优点:

  • 结构描述明确。

缺点:

  • typedef过时的风险,重构时出现bug的概率较高。

正面案例

使用Pick提取所需表单字段:

type FormFields = Pick<User, 'email' | 'name'>;

User中的更改会自动反映在表单中。

优点:

  • 类型同步有保障。

缺点:

  • 需要控制以避免选择不支持业务逻辑的额外字段。