编程高级TypeScript开发者

在TypeScript中,Mapped Types是什么,如何利用它们创建灵活的泛型类型?请详细阐述它们的使用细节和潜在的陷阱。

用 Hintsage AI 助手通过面试

回答。

Mapped Types是通过动态地转换(重命名、修改)另一个类型的所有属性而构建的类型。其语法基于in构造:

type Readonly<T> = { readonly [K in keyof T]: T[K]; } type User = { name: string; age: number; } const u: Readonly<User> = { name: 'Eve', age: 22 }; u.name = 'Bob'; // 错误:name为只读

细节:

  • 可以通过关键字-?+?来修改修饰符(readonly、optional),移除或添加它们。
  • 可以嵌套使用,与条件类型、工具类型和泛型组合使用。
  • 在开发阶段,特别是在复杂的嵌套类型修改时,错误的追踪并不总是容易。

包含所有修饰符的示例:

type PartialMutable<T> = { -readonly [K in keyof T]?: T[K]; };

陷阱问题。

"应用带有optional修饰符的mapped type,是否仅影响第一级属性,还是嵌套对象也会受影响?"

回答: 不,带有optional ?的mapped type仅影响第一级属性。嵌套对象需要单独转换,通常使用递归或额外的mapped types。

示例:

type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]; };

由于对该主题的细节了解不足而导致的实际错误示例。


故事

在一个项目中,为了节省时间,使用了标准的Partial<T>来处理深层表单。然而,第二和第三层级的字段并未设置为可选,导致在缺少嵌套键时运行时出现意外错误。


故事

曾试图仅在子对象中删除readonly属性,结果仅对顶层应用了mapped type:

type Mutable<T> = { -readonly [K in keyof T]: T[K] }

结果,类型为{ readonly foo: { readonly bar: number } }的字段在嵌套中保持不变,导致团队困惑并增加了维护难度。


故事

在复杂的数据模型中,应用了嵌套的mapped types以合并多个工具类型(例如,Readonly & Partial)。由于组合顺序错误,产生了意外的类型兼容性冲突,导致编译器开始输出混乱的错误信息。