TypeScript 映射类型:DRY 的类型编程

映射类型让 TypeScript 类型可以"批量加工":全变可选、全变只读、属性重命名。本文讲解映射类型语法、修饰符控制与可复用类型工具的构建。

最佳实践
类型结构与组件组合插画

映射类型用 { [K in keyof T]: T[K] } 语法遍历旧类型的每个属性生成新类型——内置的 Partial、Required、Readonly、Pick 全是它实现的。掌握它,你就掌握了 TypeScript 类型系统的"元编程"能力。

解决什么问题

interface User { id: number; name: string; email: string; }

// 需求:一个"更新用户"的类型,所有字段可选
// 笨办法:再写一遍,每个字段加 ? —— User 改了它就漂移
interface UserUpdate { id?: number; name?: string; email?: string; }

映射类型把"再写一遍"变成"一条规则":

type UserUpdate = { [K in keyof User]?: User[K] };
// 这就是内置 Partial<User> 的实现原理

User 加字段,UserUpdate 自动跟上——类型也 DRY。

修饰符的增与删

type Mutable<T> = { -readonly [K in keyof T]: T[K] };      // 去掉只读
type Required2<T> = { [K in keyof T]-?: T[K] };            // 去掉可选(内置 Required)
type Nullable<T> = { [K in keyof T]: T[K] | null };        // 全加 null

+/- 前缀控制修饰符的添加与移除(+ 是默认)——readonly 和 ? 都可以双向操作。

键重映射:as 子句

// 属性名加前缀
type Prefixed<T, P extends string> = {
  [K in keyof T as `${P & string}${Capitalize<string & K>}`]: T[K]
};
type ApiUser = Prefixed<User, 'api'>;
// { apiId: number; apiName: string; apiEmail: string }

// 过滤属性:键重映射为 never 即排除
type OnlyStrings<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K]
};

键重映射(TS 4.1+)让映射类型从"批量改属性"升级为"筛选与重构属性集"。

构建可复用类型工具

// 深度只读
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
};

// 把指定键变可选
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

// 事件 Map 模式:为每个数据键生成变更回调
type ChangeHandlers<T> = {
  [K in keyof T as `on${Capitalize<string & K>}Change`]: (value: T[K]) => void
};

这套"类型工具库"思路是大型 TS 项目基建的一部分——表单库、状态管理、API 层都在用。

与条件类型联用

映射类型遍历结构,条件类型做分支——两者合体即是类型编程的完整工具箱。内置的 Pick、Omit、Record 本质都是这个组合的封装。

常见问题(FAQ)

Q:keyof 拿到的是什么?

类型所有键的联合('id' | 'name' | 'email')。映射类型的 K in keyof T 就是对这个联合的遍历。

Q:映射类型会影响性能吗?

类型层面的计算只发生在编译期,运行时零成本。但超深的递归映射会拖慢编译——类型体操适可而止。

Q:什么时候不该用映射类型?

目标类型与源类型没有系统性关联时(比如 API 响应与前端模型差异巨大),硬用映射不如直接定义新接口清晰。映射类型服务的是"衍生关系明确"的场景。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台