首页/新闻资讯/正文详情

《The Concise TypeScript Book》精讲:TypeScript 映射类型修饰符(Mapped Type Modifiers)完全指南

发布时间:2026/9/24 20:16:32 来源:云帆数科 栏目:资讯中心
《The Concise TypeScript Book》精讲:TypeScript 映射类型修饰符(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点击查看免费下载映射类型Mapped Types允许我们基于既有类型逐属性生成新类型而映射类型修饰符Mapped Type Modifiers则是在这个过程中控制每个属性只读性与可选性的关键语法。本文以开源仓库 typ/typescript-book 中 mapped-type-modifiers.md 章节为骨架结合同书 mapped-types.md、readonly-properties.md、optional-properties.md 与 type-manipulation.md 等章节系统讲解readonly、-readonly、?三个修饰符的语法、语义与实战组合读完后你将能够手写ReadonlyT、PartialT等工具类型的等价实现并在自己的类型体系中自如地加锁与解锁属性。一、前置基础先理解映射类型本身在讨论修饰符之前必须先明确它们作用的载体——映射类型。按照本书 mapped-types.md 章节的定义Mapped Types 允许你基于一个既有类型通过映射函数逐属性变换创建出新类型。通过映射既有类型你可以创建以不同格式表达相同信息的新类型。创建映射类型需要两步用keyof取出既有类型的全部属性键再用索引签名[P in keyof T]遍历这些键并用索引访问类型T[P]取出每个属性的原始类型进行变换。原章节给出的核心示例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], };这里MyMappedTypeT遍历T的每个属性P把每个属性的类型T[P]包装成数组T[P][]于是MyNewType与MyType表达相同的信息但每个属性的形态都从标量变成了数组。映射类型修饰符就是在这段[P in keyof T]的声明处附加readonly、?等标记从而在复制结构的同时改变属性的可变性与可选性。二、三个核心修饰符总览本章节 mapped-type-modifiers.md 明确指出TypeScript 的映射类型修饰符共有三类能力修饰符语义作用readonly或readonly在映射结果中把属性标记为只读属性只能读取不能重新赋值-readonly在映射结果中把属性恢复为可变解除上层类型或映射带来的只读约束?在映射结果中把属性标记为可选属性可以缺省赋值的对象可以不提供该键注意前缀是显式写法readonly与readonly完全等价而-前缀是移除语义只能作用于映射类型内部用于把已有修饰符剥离掉。下面逐一展开。三、readonly/readonly批量加只读锁原章节给出的第一个示例type ReadOnlyT { readonly [P in keyof T]: T[P] }; // All properties marked as read-only这个泛型类型接收任意对象类型T遍历其全部属性并在每个属性前加上readonly。它的效果等价于把T的每个属性都用readonly重新声明一遍。回顾本书 readonly-properties.md 章节对只读属性的解释使用readonly修饰符可以阻止对属性的写入它确保属性不能被重新赋值但不提供完全不可变total immutability的保证。也就是说readonly只约束引用层面的赋值不阻止属性内部如嵌套对象、数组元素的修改。这是使用只读类型时最容易踩的坑readonly是浅层的。readonly是它的显式等价形式在需要强调添加语义与后面的-对应时使用type ReadOnlyExplicitT { readonly [P in keyof T]: T[P] }; // 与 readonly 写法完全等价下面演示实际使用效果type User { name: string; age: number; }; type ReadonlyUser ReadOnlyUser; // 等价于 { readonly name: string; readonly age: number; } const user: ReadonlyUser { name: Simon, age: 17 }; user.name John; // 编译错误无法为只读属性赋值值得注意的是readonly修饰符同样适用于索引签名。在 readonly-properties.md 中给出了如下声明形式type K { readonly [index: number]: string; };这说明只读修饰符不仅可以加在具名属性上也可以加在索引签名上从而锁定整个字典不可被改写。四、-readonly解除只读实现MutableT原章节的第二个示例展示了反向操作type MutableT { -readonly [P in keyof T]: T[P] }; // All properties marked as mutable-readonly表示移除只读修饰符它把输入类型中所有readonly属性全部还原为可变属性。这在处理来自外部库、as const断言或ReadonlyT包装过的类型时非常实用type Config { readonly apiUrl: string; readonly retries: number; }; type MutableConfig MutableConfig; // 等价于 { apiUrl: string; retries: number; } const config: MutableConfig { apiUrl: https://api.example.com, retries: 3 }; config.retries 5; // 合法MutableConfig 的属性已可写语法上readonly与-readonly是一对添加/移除操作?同样存在对应的-?移除形式详见第六节。注意-前缀必须紧跟在属性声明位置且-readonly只能出现在映射类型中不能用于interface或普通对象类型。五、?批量将属性变为可选原章节的第三个示例type MyPartialT { [P in keyof T]?: T[P] }; // All properties marked as optional?修饰符把T的每个属性都标记为可选。这与 optional-properties.md 章节中在属性名末尾加问号?即声明可选属性的规则一脉相承type X { a: number; b?: number; // Optional };映射版本MyPartialT则把每个属性都可选这件事自动化。它的典型使用场景包括配置合并用户只提供部分配置、表单部分更新PATCH 语义、测试替身等type Settings { theme: string; fontSize: number; showLineNumbers: boolean; }; type PartialSettings MyPartialSettings; // 等价于 { theme?: string; fontSize?: number; showLineNumbers?: boolean; } const patch: PartialSettings { fontSize: 14 }; // 只更新一个字段合法配合可选属性的默认值技巧同样出自 optional-properties.md可以在消费方优雅地处理缺省值const mergeSettings ({ theme dark, fontSize 16, showLineNumbers true }: PartialSettings) ({ theme, fontSize, showLineNumbers, });六、组合使用与-?同时操控两个维度三个修饰符之间可以自由组合。最典型的组合是既只读又可选这正是内置ReadonlyPartialT的效果type ReadonlyPartialT { readonly [P in keyof T]?: T[P] }; // 每个属性readonly 且 optional反过来映射类型也支持-?来移除可选性把可选属性恢复为必填type MyRequiredT { [P in keyof T]-?: T[P] }; // 移除 ?所有属性必填这一写法与-readonly对称-前缀统一表示剥离修饰符。RequiredT工具类型的标准实现正是基于-?的参见下文与 type-manipulation.md 中RequiredT的说明。同时移除只读与可选type ConcreteT { -readonly [P in keyof T]-?: T[P] }; // 所有属性可变且必填一个完整的读写权限变换实战示例type Draft { title?: string; body?: string; }; // 发布前要求所有字段齐全-?并且一旦发布不可再改readonly type Published { readonly [P in keyof Draft]-?: Draft[P] }; // 等价于 { readonly title: string; readonly body: string; } const post: Published { title: Hello, body: World }; post.title Hi; // 编译错误readonly七、与内置工具类型的关系ReadonlyT、PartialT、RequiredT的本质本书 predefined-conditional-types.md 与 type-manipulation.md 两个章节列出了大量内置工具类型其中与映射类型修饰符直接相关的有三个内置工具类型文档定义本质映射类型等价实现ReadonlyT将 T 的所有属性设为 readonly{ readonly [P in keyof T]: T[P] }PartialT将 T 的所有属性设为可选{ [P in keyof T]?: T[P] }RequiredT将 T 的所有属性设为必填{ [P in keyof T]-?: T[P] }其中Partial与Required互为逆操作Readonly与手写的MutableT互为逆操作。这正是本章节三个示例ReadOnly、Mutable、MyPartial的深层意义它们实际上是在重新发明语言内置的工具类型让你理解工具类型不是魔法而是映射类型 修饰符的语法糖。在 type-manipulation.md 中可以看到这些工具类型的具体使用示例type Person { name: string; age: number; }; type A PartialPerson; // { name?: string | undefined; age?: number | undefined; } type B Required{ name?: string; age?: number }; // { name: string; age: number; } type C ReadonlyPerson; const a: C { name: Simon, age: 17 }; a.name John; // Invalid注意一个细节PartialT在严格模式strictNullChecks 开启下会为每个可选属性附加| undefined。这源于可选属性在严格模式下意味着可能缺失也可能为 undefined的语言语义与本书 strictnullchecks.md 章节所讲的严格空值检查行为一致。八、深入原理同态映射、修饰符保留与浅层只读8.1 同态映射修饰符默认被保留当映射类型直接使用[P in keyof T]不附加任何修饰符时TypeScript 会原样保留输入类型T中已有的readonly与?修饰符。这种保形复制的映射被称为同态homomorphic映射。也就是说type CopyT { [P in keyof T]: T[P] }; type Source { readonly id: number; label?: string; }; // CopySource 仍是 { readonly id: number; label?: string; } // 只读与可选修饰符都被保留了下来如果希望复制结构的同时强制改变修饰符就必须显式使用/-前缀或直接书写修饰符如readonly、?。这正是-readonly、-?存在的意义——默认行为是保留主动移除才需要减号。8.2readonly的浅层性不是深度不可变再次强调 readonly-properties.md 中的警告readonly不提供任何完全不可变的保证。例如type ReadonlyUser { readonly profile: { nickname: string } }; const user: ReadonlyUser { profile: { nickname: simon } }; user.profile { nickname: other }; // 编译错误profile 是 readonly user.profile.nickname other; // 合法嵌套对象内部仍然可写如果需要深度只读必须递归地让每个嵌套属性都经过映射处理可结合条件类型实现递归映射这不是单个readonly修饰符能完成的。8.3 修饰符只能作用于映射类型内部readonly、-readonly、?、-?这些映射修饰符只能出现在映射类型{ [P in ...] ... }中。在普通对象类型、interface中书写-readonly或-?会直接报语法错误。interface中可用的只有声明形式的readonly与?见 optional-properties.md 与 readonly-properties.md。8.4 键重映射修饰符之外的第三种变换除了修饰符映射类型还支持用as子句重写键名这是映射类型三大变换能力改修饰符、改类型、改键名之一。在 exploring-the-type-system.md 的 Type Assertion 小节中给出了一个将修饰符、键重映射与模板字面量类型结合的示例type JType { [Property in keyof Type as prefix_${string Property}]: () Type[Property]; }; type X { a: string; b: number; }; type Y JX; // 等价于 { // prefix_a: () string; // prefix_b: () number; // }这里as \prefix_${string Property}把每个键重命名为带prefix_前缀的新键值类型则从属性类型变换为返回该类型的函数。虽然这不是修饰符的职责但理解as键重映射能让读者把映射类型这一整套能力keyof遍历 T[P]取类型 修饰符改可变性 as 改键名完整串起来。九、实战用一个综合案例串联全部修饰符下面把本章节三个示例改造成一个贴近真实项目的场景——数据模型的草稿可变可选→ 冻结只读必填生命周期// 1. 基础模型所有字段必填、可写 type Article { title: string; content: string; tags: string[]; }; // 2. 草稿态字段全部可选方便增量编辑等价于 PartialArticle type ArticleDraft { [P in keyof Article]?: Article[P] }; // 3. 发布态字段全部必填且只读组合使用 ? 移除与 readonly 添加 type PublishedArticle { readonly [P in keyof Article]-?: Article[P] }; // 4. 如果从外部如 API 响应或 as const 常量拿到的是只读类型 // 用 -readonly 解除锁便于在本地修改 declare const fetched: { readonly title: string; readonly content: string; readonly tags: string[] }; type MutableArticle { -readonly [P in keyof typeof fetched]: (typeof fetched)[P] }; // 5. 使用 const draft: ArticleDraft { title: Draft title }; // 合法其余字段可选 const published: PublishedArticle { title: T, content: C, tags: [ts] }; published.title T2; // 编译错误readonly这个案例中?、-?、readonly、-readonly四种映射修饰符全部登场分别对应放宽输入约束与收紧输出约束两种方向展示了映射类型修饰符在数据流边界表单、持久化、接口层上的典型用法。十、小结与延伸阅读映射类型修饰符是 TypeScript 类型系统的格式化工具readonly/readonly批量加只读锁-readonly批量解锁?批量放宽为可选-?批量收紧为必填默认的同态映射会保留既有修饰符显式的前缀操作符则用于强制改变它们。掌握这四个操作符你就掌握了ReadonlyT、PartialT、RequiredT等内置工具类型的实现原理能够在任何需要以类型为输入、以类型为输出的场景中写出精确的类型变换。本文对应的原文档位于 mapped-type-modifiers.md它在全书的目录结构中紧随 mapped-types.md见 table-of-contents.md 第 38、39 章。建议按以下顺序继续深入mapped-types.md映射类型的基础语法keyof[P in keyof T]T[P]readonly-properties.md 与 optional-properties.md只读与可选属性的声明语法type-manipulation.mdPartial、Required、Readonly等内置工具类型的完整清单与用法exploring-the-type-system.md包含as键重映射在内的更高级类型操作predefined-conditional-types.md条件类型视角下的工具类型速查表。赞分享文档教程【免费下载链接】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点击查看免费下载相关推荐BabelDOC突破性智能排版保留的PDF文档翻译解决方案BabelDOC突破性智能排版保留的PDF文档翻译解决方案 BabelDOC是一款专为学术和商业文档设计的智能翻译工具通过先进的排版分析和结构重建技术在保人工智能AI 应用NLP计算机视觉The Concise TypeScript Book 精讲函数返回类型推断Type from Func Return原理与实战The Concise TypeScript Book 精讲函数返回类型推断Type from Func Return原理与实战 本篇技术指南以开源仓库文档教程poly_data进阶技巧使用process_live实现实时数据流处理poly_data进阶技巧使用process_live实现实时数据流处理 poly_data是一个强大的Polymarket数据检索工具能够高效获取、处理和文档教程上一篇unified国际化支持多语言内容处理完整方案下一篇前端开发者必备You-Dont-Need-JavaScript项目完全使用手册创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

从零实现ID3与C4.5决策树:贷款审批规则提取实战
从零实现ID3与C4.5决策树:贷款审批规则提取实战

1. 项目背景与整体思路最近在做贷款审批的规则梳理,我把 ID3 和 C4.5 两个经典决策树算法从零写了一遍,用一份贷款申请样本数据把建树、预测、剪枝和调参的完整流程重新跑通。先说结论:今天做风控建模,XGBoost、LightGBM 这些模型… · 2026/9/24 20:16:32

模仿不是抄袭:一套从拆解对标到原创的低成本进阶方法论
模仿不是抄袭:一套从拆解对标到原创的低成本进阶方法论

先说明一句:这篇文章没有要劝你“抄”谁,恰恰相反,我特别想聊清楚一件事——为什么很多人一听到“模仿”就皱眉,觉得那是没本事的人才会干的事,但实际上,模仿恰恰是成本最低、见效最快的进阶方式&#xff0… · 2026/9/24 20:16:32

工业边缘计算实战:人工智能+产线改造的第一站与避坑指南
工业边缘计算实战:人工智能+产线改造的第一站与避坑指南

这几年做工厂智能化改造的朋友应该都有同感:大家聊“人工智能”聊得火热,但真正落到车间里,最先让你挠头的往往不是算法,而是数据怎么接、模型往哪放、掉线了怎么办。我在这行摸爬滚打久了,越来越确信一个判断——“人… · 2026/9/24 20:16:32

ARIMAX多变量时序预测实战:外生变量建模与业务归因
ARIMAX多变量时序预测实战:外生变量建模与业务归因

简介:本资源是一套基于ARIMAX(自回归积分滑动平均外生变量)模型的多变量时间序列预测完整实现,面向具备Python基础与统计建模经验的数据分析学习者、算法工程师及高校科研人员,适用于经济指标、能源负荷、交通流量等含… · 2026/9/24 20:47:31

Python+CNN车牌识别实战:从定位分割到边缘部署全链路解析
Python+CNN车牌识别实战:从定位分割到边缘部署全链路解析

简介:本资源是一套面向计算机专业本科生与AI初学者的停车场智能车牌识别系统完整实现方案,聚焦于目标检测与字符识别双阶段任务,适用于课程设计、期末大作业及小型智能交通项目实践。项目基于Python开发,融合CenterNet实现车牌区域… · 2026/9/24 20:47:31

Windows下chm文件打不开?用regsvr32修复itss.dll的完整指南
Windows下chm文件打不开?用regsvr32修复itss.dll的完整指南

1. 从一次双击无响应说起:chm 文件为什么突然打不开了很多人第一次遇到.chm文件打不开,场景都差不多:从同事那儿拷来一份技术手册,或者从某个老项目资料包里翻出一份 API 文档,双击之后要么毫无反应,要么弹… · 2026/9/24 20:47:31

5G基站BBU深度拆解:架构演进、核心功能与部署实战
5G基站BBU深度拆解:架构演进、核心功能与部署实战

1. 拆开5G基站:BBU到底藏在哪一层很多人第一次听到BBU这个词,脑子里浮现的可能是机房角落里某个不起眼的铁盒子。但如果你真的走进一个典型的5G基站站点,你会发现BBU通常被安装在标准19英寸机柜里,和电源模块、传输设备挤在一起&a… · 2026/9/24 20:47:31

图转PPT技术解析:OCR、版面还原与可编辑PPTX生成实践
图转PPT技术解析:OCR、版面还原与可编辑PPTX生成实践

1. 从"一句话生成PPT"说起:这个需求到底卡在哪先抛一个我自己的真实经历。去年有段时间我频繁帮团队做技术分享,每周至少两场,每场20页左右的PPT。最开始我图省事,直接找那种"输入一句话,AI帮你生成整套… · 2026/9/24 20:47:31

CLIP4Clip视频检索工程实践:Adapter微调+关键帧缓存
CLIP4Clip视频检索工程实践:Adapter微调+关键帧缓存

简介:本资源是一套面向计算机专业本科生与研究生的毕业设计级视频文本检索系统实现方案,聚焦CLIP模型在资源受限场景下的轻量化优化与工程落地。针对传统CLIP微调训练耗时长、显存占用高问题,项目提出关键帧保存策略与Adapter Tuning双路径优… · 2026/9/24 20:47:24

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码