新闻详情

新闻详情

首页 / 资讯中心 / 详情

The Concise TypeScript Book 精读:映射类型修饰符(Mapped Type Modifiers)全解

发布时间:2026/9/27 7:37:52来源:尧图网络
The Concise TypeScript Book 精读:映射类型修饰符(Mapped Type Modifiers)全解
文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载映射类型修饰符是 TypeScript 在「映射类型」基础上提供的一组类型级开关让你在对既有类型逐属性变换时同步调整每条属性的只读性与可选性。本指南以开源仓库 The Concise TypeScript Book 的 es 版映射类型修饰符章节 为骨架结合仓库中映射类型、只读属性、可选属性等相邻章节与类型系统源码级说明带你从语法到实战完整掌握readonly、-readonly、?三种修饰符的用法、加减法语法、与内置工具类型的关系及其边界限制。读完你将能够自己写出ReadOnlyT、MutableT、MyPartialT这类可复用的类型工具并理解ReadonlyT、PartialT、RequiredT等标准库工具类型的底层实现原理。一、先理解载体映射类型Mapped Types修饰符本身不能单独使用它必须出现在映射类型的遍历语法之中。所谓映射类型就是基于一个既有类型通过keyof取出其全部键再逐一对每个键的取值类型进行变换最终产出一个全新类型。仓库的 映射类型章节 给出了最典型的骨架type MyMappedTypeT { [P in keyof T]: T[P][]; }; type MyType { foo: string; bar: number; }; type MyNewType MyMappedTypeMyType; const x: MyNewType { foo: [hello, world], bar: [1, 2, 3], };这里[P in keyof T]是遍历语法P依次取到T的每个键右侧T[P]索引访问类型取出该键对应的值类型再包装成数组。于是MyType的foo: string与bar: number被映射成foo: string[]与bar: number[]——信息不变形态改变这正是映射类型的核心价值。而映射类型修饰符则负责在遍历过程中额外控制每条属性的readonly只读与?可选属性。它们写在属性名之前、与[P in keyof T]同处一个位置type X { readonly [P in keyof T]: T[P] }; // 修饰符位于遍历语法之前二、三种核心修饰符语法与语义原文档将修饰符归纳为三类以下逐一展开。2.1readonly/readonly把属性变为只读在映射类型中为每条属性加上readonly即可让结果类型的全部属性不可重新赋值type ReadOnlyT { readonly [P in keyof T]: T[P] }; // All properties marked as read-onlyreadonly与readonly语义完全等价——表示「显式添加该修饰符」是冗余但更明确、可读性更好的写法type ReadOnlyT { readonly [P in keyof T]: T[P] }; // 与上一写法等价两者都是添加只读约束。若省略前缀直接写readonlyTypeScript 同样视为添加。2.2-readonly把属性变回可变-readonly是readonly的逆操作用于移除既有类型上的只读标记让属性恢复可写type MutableT { -readonly [P in keyof T]: T[P] }; // All properties marked as mutable注意-只能配合修饰符使用如-readonly、-?单独写-本身没有意义。/-前缀的引入TypeScript 2.8 起使得修饰符不再是单向追加而是可加可删这也是实现RequiredT等工具类型的语法基础。2.3?把属性标记为可选在映射类型中加入?会让结果类型的所有属性变为可选即属性可以缺失type MyPartialT { [P in keyof T]?: T[P] }; // All properties marked as optional这里的?与普通对象类型中b?: number的语义一致——仓库的 可选属性章节 中特别说明可选属性可通过解构赋默认值来兜底type X { a: number; b?: number; }; const x ({ a, b 100 }: X) a b;同样地-?即-加?可以移除可选标记强制所有属性必填这正是内置RequiredT的做法type MyRequiredT { [P in keyof T]-?: T[P] }; // All properties marked as required三、原文档完整示例三种工具类型一次到位原文档用三个并排定义的泛型工具类型直观展示了三种修饰符的独立用法这是本主题最核心的实操片段完整保留如下type ReadOnlyT { readonly [P in keyof T]: T[P] }; // All properties marked as read-only type MutableT { -readonly [P in keyof T]: T[P] }; // All properties marked as mutable type MyPartialT { [P in keyof T]?: T[P] }; // All properties marked as optional配合一个实际类型走一遍全流程type Person { readonly name: string; // 原本就是只读 age: number; }; // 1) 全部变成只读 type FrozenPerson ReadOnlyPerson; // { readonly name: string; readonly age: number; } // 2) 全部变回可变含原本 readonly 的 name type EditablePerson MutablePerson; // { name: string; age: number; } // 此时 name 可以被重新赋值 // 3) 全部变成可选 type PartialPerson MyPartialPerson; // { readonly name?: string; age?: number; }一个关键观察MutableT能同时把原本声明为readonly的属性解除只读这正是-readonly存在的原因——单靠readonly只能加不能减有了-前缀后映射类型才具备双向调整能力。四、组合使用同时控制只读与可选修饰符不是互斥的它们可以自由叠加在同一映射类型上形成四种组合// 全部只读 全部可选 type ReadonlyPartialT { readonly [P in keyof T]?: T[P] }; // 全部可变 全部可选等价于去掉 readonly 的 Partial type MutablePartialT { -readonly [P in keyof T]?: T[P] }; // 全部只读 全部必填 type ReadonlyRequiredT { readonly [P in keyof T]-?: T[P] }; // 全部可变 全部必填等价于 RequiredMutableT type MutableRequiredT { -readonly [P in keyof T]-?: T[P] };这种组合能力在实战中非常常见例如「接口返回的字段都是必填但前端修改表单时希望它们全部变为可选且可变」一条映射类型即可完成type ApiUser { readonly id: number; readonly name: string; readonly email: string; }; // 表单编辑态去掉只读、允许部分字段缺失 type EditableForm { -readonly [P in keyof ApiUser]?: ApiUser[P] }; // { id?: number; name?: string; email?: string; }五、与内置工具类型的对应关系你可能已经注意到上面手写的ReadOnlyT、MyPartialT与 TypeScript 标准库内置的ReadonlyT、PartialT几乎一模一样。事实上映射类型修饰符正是这些内置工具类型的底层实现机制。仓库的 类型操作章节 系统整理了这些内置工具类型的语义PartialT构造一个把T所有属性都设为可选的类型RequiredT构造一个把T所有属性都设为必填的类型ReadonlyT构造一个把T所有属性都设为只读的类型其效果与readonly [P in keyof T]完全一致。例如ReadonlyT的等价手写实现就是我们上面定义的ReadOnlyT而RequiredT对应{ [P in keyof T]-?: T[P] }。仓库 只读属性章节 还展示了readonly在普通类型与索引签名中的表现interface Y { readonly a: number; } type X { readonly a: number; }; type J Readonly{ a: number; }; type K { readonly [index: number]: string; // 只读索引签名 };需要特别强调的是J Readonly{ a: number }与手写{ readonly a: number }得到的类型结构完全相同——因为在结构类型系统下仓库 探索类型系统章节 有专述类型由结构决定而非声明方式决定所以「用内置工具」和「手写修饰符」在编译层面等价你可以按可读性任选其一。六、实战场景与注意事项6.1 从 API 响应派生「不可变」快照后端返回的领域对象往往在业务层不应被随意改写可以把它包装为只读版本作为跨模块传递的只读快照type ApiOrder { id: string; items: string[]; total: number; }; type ImmutableOrder ReadonlyApiOrder; // { readonly id: string; readonly items: string[]; readonly total: number; } function render(order: ImmutableOrder) { // order.total 0; // 编译错误Cannot assign to total because it is a read-only property }6.2 解除第三方库类型的只读约束当你拿到一个被ReadonlyT包裹的入参类型又需要在本地做变更时-readonly就是唯一的「解药」type LockedConfig Readonly{ host: string; port: number }; // 本地可变副本 type MutableConfig { -readonly [P in keyof LockedConfig]: LockedConfig[P] }; // { host: string; port: number }6.3 注意只读是类型层面的契约不是运行时保证原文档及 只读属性章节 都反复强调一个边界readonly只保证编译期不能重新赋值并不提供任何运行时不可变性不产生任何运行时效果。例如type Config Readonly{ retries: number }; const cfg: Config { retries: 3 }; // cfg.retries 5; // 编译错误 // 但类型断言可以绕过运行时并不阻止写入 (cfg as { retries: number }).retries 5; // 合法同理readonly是浅层的它只禁止对属性本身重新赋值不禁止修改属性内部的内容如数组元素、嵌套对象字段。若要深度不可变需要递归组合ReadonlyT或借助as const等额外手段这超出了修饰符本身的职责范围。6.4 可选属性与strictNullChecks的联动映射出可选属性后在访问时 TypeScript 会要求先做存在性判断仓库 strictnullchecks 章节 对此有专门论述。因此由?派生出的类型在读取字段时通常需要配合if (obj.field ! undefined)或可选链obj?.field这是使用MyPartialT类工具时的常见伴生约束。七、进阶延伸修饰符不是唯一变换维度掌握readonly、?、/-之后你会自然联想到一个更广泛的问题既然遍历[P in keyof T]可以修改属性特性是否也能修改键本身答案是肯定的——在更高级的映射类型中可以使用as子句对键做重映射如[P in keyof T as NewKey]从而筛选、改名或联合模板字面量生成新键。但仓库本主题章节并未涉及该语法此处仅作为方向提示修饰符解决的是「属性的状态」as重映射解决的是「键的身份」两者叠加即可写出Pick、Omit、Record这类更复杂的标准工具类型它们的语义说明同样收录于 类型操作章节。八、小结语法位置修饰符写在映射类型遍历语法[P in keyof T]之前。readonly/readonly为所有属性添加只读约束-readonly反向移除。?将属性标记为可选-?将可选移除、恢复必填。组合自由readonly与?可任意搭配配合/-实现四种象限。与标准库同源ReadonlyT、PartialT、RequiredT的底层就是这些修饰符手写与内置在结构类型系统下等价。边界清晰readonly是浅层、编译期约束不提供运行时不可变性。掌握了这组修饰符你不仅能读懂标准库工具类型的实现还能按需定制出自己的类型变换工具——这正是 The Concise TypeScript Book 将「映射类型」与「映射类型修饰符」设为相邻章节第 38、39 节的用意所在。想进一步巩固可回看仓库的 映射类型章节、只读属性章节 与 可选属性章节并用 TypeScript Playground 或本地tsc逐一验证上文所有示例。赞分享文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载相关推荐《The Concise TypeScript Book》精讲TypeScript 映射类型修饰符Mapped Type Modifiers完全指南《The Concise TypeScript Book》精讲TypeScript 映射类型修饰符Mapped Type Modifiers完全指南 映射文档教程kkFileView 如何在 GitHub Actions 中配置 PR 与 Nightly 自动运行预览 E2E 回归kkFileView 如何在 GitHub Actions 中配置 PR 与 Nightly 自动运行预览 E2E 回归 kkFileView 仓库已经内置了两文档教程Windmill App Builder 组件扩展指南从零添加一个前端 App 组件Windmill App Builder 组件扩展指南从零添加一个前端 App 组件 导读 Windmill 是一个开源开发者平台其内置的 App Buil文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

网站被黑挂马急!从零搭建到做关键词优化的安全实战 2026/9/27 7:37:49

网站被黑挂马急!从零搭建到做关键词优化的安全实战

网站被黑挂马急!从零搭建到做关键词优化的安全实战 你的服务器刚发出警报,页面弹出一堆乱七八糟的博彩广告,后台密码突然失效,这种 网站被黑挂马不知道怎么办…

阅读更多 →
交换机环路导致整网变慢:广播风暴的判据与定位处置步骤 2026/9/27 7:37:42

交换机环路导致整网变慢:广播风暴的判据与定位处置步骤

「昨天还好好的,今天整个楼层都上不了网」,同时交换机指示灯整齐地高频闪烁——这类报修在二层网络里有一个高频成因:环路引发的广播风暴。它的特点是影响范围是整段广播域,且和网络出口、宽带带宽无关,用错排查方向会…

阅读更多 →
MySQL用户行为与销售数据分析 2026/9/27 7:37:36

MySQL用户行为与销售数据分析

在数据驱动的商业环境中,理解客户行为与销售数据已成为推动业务发展的核心。通过分析用户行为数据和销售数据,可以识别用户模式、优化业务策略,从而促进客户转化和提升销售业绩。 本文旨在介绍如何使用MySQL分析用户行为数据和销售数据,帮助自学编程的读者掌握核心的SQL数…

阅读更多 →
MySQL时间序列分析与趋势预测 2026/9/27 7:37:36

MySQL时间序列分析与趋势预测

时间序列数据是指按时间顺序排列的观测数据序列,其在金融、制造、零售等领域有广泛应用。利用时间序列分析,能够揭示数据的内在规律,识别历史趋势并预测未来走势。在数据库中,时间序列分析可以帮助理解业务模式,如每月销售量的增长或波动趋势,甚至还能为库存管理提供有效…

阅读更多 →
OpenPNP 操作ESP32 的bug 2026/9/27 7:37:36

OpenPNP 操作ESP32 的bug

openPNP 操作ESP32 时,某些情况下无法正常运行。 板卡上USB2TTL Ch340 芯片带EN,IO0在线烧录功能。无法控制RTS 信号的电平,导致板卡始终处于复位状态。去除硬件的链接即可使用。 或者重新编译openPNP. 这是在调试中遇见的bug.

阅读更多 →
用智一刻3步选对论文选题工具,告别生搬硬套 2026/9/27 7:37:36

用智一刻3步选对论文选题工具,告别生搬硬套

每年定开题报告时,很多同学都会被导师打上一句批注:“缺少理论分析工具,论文深度不够,像在写工作总结。” 为了交差,不少人开始到网上去搜理论,什么宏大战略管理理论、复杂系统演化模型统统往上套。结果开…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉