
教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载本篇技术指南以 TypeHero 仓库中的 Advent of TypeScript 2024 第 4 天挑战challenges/aot/2024/4/prompt.md为核心完整还原圣诞礼物派送地址清单这个类型挑战的题目设定、起始代码、测试用例与标准解法并深入拆解 TypeScript 映射类型Mapped Type的底层语法原理。读完本文你将掌握[K in keyof T]这套语法从原样拷贝结构到批量改写属性值类型的完整演化路径并能独立完成同类将对象所有属性值统一替换为指定类型的泛型工具类型设计。挑战背景北极厨房里的圣诞故事挑战以一段发生在北极工坊茶水间的对话开场——12 月 4 日清晨圣诞老人Santa与精灵总管伯纳德Bernard发生了争执。伯纳德抱怨 200 多年来一直以骨干团队skeleton-crew运转强烈要求扩招圣诞老人则以咱们还是一家创业公司startup的奋斗文化话术安抚他。伯纳德愤愤离去自言自语道看来又得拖着身子去刷一道毫无实际应用价值的 TypeScript 类型挑战了。可怜的伯纳德让我们帮帮他。——这正是本道挑战的由来。这段叙事与仓库中其他 Advent of TypeScript 挑战如第 3 天的 Christmas Cookie Inventory围绕曲奇库存盘点一样将抽象的泛型类型技巧包装进一个具体、有趣的圣诞工作流场景中。任务定义泛型类型PresentDeliveryList题目的核心要求如下今天的任务是创建一个类型PresentDeliveryList它接收一个对象类型作为输入然后将每个属性的值替换为Address。我们事先不知道会提供哪些属性因此它必须是一个泛型类型generic type。否则伯纳德大概只会复制粘贴copy/pasta混过这一天。从源码结构看本挑战的难度等级在 metadata.json 中被标记为difficulty: event节日活动挑战label为 2024 Day Four作者为 TypeHero。起始代码user.ts挑战的初始模板位于 user.ts全文如下type Address { address: string; city: string }; type PresentDeliveryList unknown;可以看到目标替换目标类型Address已经定义好它是一个包含address: string和city: string两个字段的对象类型PresentDeliveryList目前被占位为unknown且不是泛型——这就是需要你补齐的部分。编译环境tsconfig.json该挑战目录下的 tsconfig.json 开启了三项严格选项这也构成了完成挑战时必须遵守的类型约束{ compilerOptions: { strict: true, exactOptionalPropertyTypes: true, noUncheckedIndexedAccess: true } }strict启用全部严格性检查包括strictNullChecks等exactOptionalPropertyTypes可选属性类型必须精确匹配不允许隐式加入undefinednoUncheckedIndexedAccess索引访问时如T[K]返回值会被认为可能为undefined促使类型设计更加严谨。从代码结构看这三项是 TypeHero 挑战体系的标准严格配置保证所有提交的解法都在严格模式下通过类型检查。测试用例解读期望的输出结构挑战的测试位于 tests.ts它通过type-testing包中的Expect与Equal工具进行严格的结构相等断言。第一个用例是一份表现混合清单type MixedBehaviorList { john: { behavior: good }; jimmy: { behavior: bad }; sara: { behavior: good }; suzy: { behavior: good }; chris: { behavior: good }; penny: { behavior: bad }; }; type test_MixedBehaviorTest_actual PresentDeliveryListMixedBehaviorList; // ^? type test_MixedBehaviorTest_expected { john: Address; jimmy: Address; sara: Address; suzy: Address; chris: Address; penny: Address; }; type test_MixedBehaviorTest Expect Equaltest_MixedBehaviorTest_actual, test_MixedBehaviorTest_expected ;第二个用例则特意选用了与礼物毫无关系的对象用于证明该类型与具体属性名无关type Unrelated { hello: { hello: hello }; world: { world: world }; }; type test_Unrelated_actual PresentDeliveryListUnrelated; // ^? type test_Unrelated_expected { hello: Address; world: Address; }; type test_Unrelated ExpectEqualtest_Unrelated_actual, test_Unrelated_expected;从这两个用例可以提炼出关键行为契约键名属性名必须原样保留——john、jimmy、hello、world一个都不能少不能增删、改名或排序每个属性的值类型全部被替换为Address与原来是什么值类型完全无关{ behavior: good }、{ hello: hello }统统变成Address必须是泛型——PresentDeliveryListT需要以...形式调用因为输入对象的形状事先未知输入对象本身不能改变——测试只用类型层面做Equal断言说明这是一次纯类型层面的投影操作。标准解法一行映射类型搞定仓库的官方解法目录 solutions/1.ts 当前为空文件等待你提交自己的解法但结合题目要求与测试契约标准解法是使用映射类型type Address { address: string; city: string }; type PresentDeliveryListT { [K in keyof T]: Address; };这个解法只有两行却完整满足了上面全部四条行为契约[K in keyof T]遍历输入对象T的所有键把每个键名原样产出为新对象的属性名: Address将每个属性的值类型统一替换为AddressT使类型成为泛型可以接收任意形状的对象类型。验证一下第一个用例PresentDeliveryListMixedBehaviorList会展开为{ john: Address; jimmy: Address; sara: Address; suzy: Address; chris: Address; penny: Address }与test_MixedBehaviorTest_expected完全相等第二个用例同理hello和world被原样保留并替换为Address。映射类型语法逐段拆解映射类型是本题的绝对核心仓库为此专门编写了系统教程 challenges/mapped-object-types/prompt.md其中对语法做了逐词拆解这里结合本挑战重新走一遍。先从什么都不做的映射类型看起它逐字逐句揭示了这套语法的含义type MovieInfoByGenreT { [K in keyof T]: T[K]; };type开始一个类型声明MovieInfoByGenre类型名称T定义名为T的泛型参数 {开始类型主体[开始一个索引签名K索引签名中代表单个键的变量名。KKey与PProperty是这类场景最常见命名TypeScript 内置类型里也大量使用但教程也提醒如果能有更贴切的描述性命名应该优先使用in映射专用的运算符表示K是右侧集合中的单个元素它驱动整个循环keyof TT的所有键组成的联合类型union: T[K]常规的类型索引。把K想象成循环中当前的键用它对T做索引就得到T中该键对应的值类型;这本质上就是对象类型里的一行property: value按常规用分号结尾};结束类型声明。关键洞察由于 TypeScript 是结构化类型系统structural type system上面这个什么都没做的映射类型产出的Example与原类型在结构上完全相同所以两者对 TypeScript 而言是等价的。而本挑战要做的正是教程中重置所有值Resetting all values那一节演示的最小改动——只改映射的右侧把T[K]换成固定的Addresstype PresentDeliveryListT { - [K in keyof T]: T[K]; [K in keyof T]: Address; };这正是从原样拷贝结构到批量改写属性值类型的关键一步映射类型允许你在: 值类型位置放置任何类型表达式既可以是T[K]保留原值类型也可以是字面量boolean、固定的具名类型Address甚至是一个条件类型。实战延伸映射类型的三种进阶变形掌握了基础写法后可以顺着同样的思路扩展出几种高频变体它们在实际项目中比统一替换更常用1. 保留原值类型但附加包装type NullableValuesT { [K in keyof T]: T[K] | null; };在: 值类型位置使用T[K]参与组合就能在保留原类型的基础上做增强——例如把每个属性变成可空。2. 依据值类型做条件改写type StringifyValuesT { [K in keyof T]: T[K] extends string ? T[K] : string; };借助条件类型extends ? :可以让映射结果与输入的具体类型动态联动已经是string的保持原样其余全部转为string。3. 键重映射Key RemappingTS 4.1type PrefixedKeysT { [K in keyof T as get${CapitalizeK string}]: T[K]; };利用as子句可以对键名本身做重映射再配合模板字面量类型实现给每个属性生成 getter 风格的新键名这类工厂类型。本挑战虽然不需要但了解它有助于理解keyof与in组合的上限。这三种变体都严格建立在[K in keyof T]同一套语法骨架上区别只在于键与值两侧的改写程度——这正是映射类型用一套循环语法解决无数日常类型转换问题的原因。验证方法如何确认解法通过本挑战是纯类型层面的练习不涉及运行时逻辑。验证方式是在 TypeScript 编译检查层面进行在 user.ts 中完成PresentDeliveryList的实现后用 TypeScript 编译器对该目录如challenges/aot/2024/4/tsconfig.json所指向的项目执行类型检查测试文件 tests.ts 中的ExpectEqual...断言会在编译期自动判定actual与expected是否结构相等若PresentDeliveryListMixedBehaviorList恰好等于{ john: Address; ... }类型检查通过若存在多出的属性、缺失的属性或值类型不符Equal断言会在编译期报错。从仓库结构看整个挑战体系如 challenges/validate.ts配套有对应的校验流程所有提交的解法都需要在开启strict、exactOptionalPropertyTypes、noUncheckedIndexedAccess的严格配置下通过编译。这也意味着你的解法必须认真对待可选属性与索引访问的边界不能依赖宽松的隐式undefined行为。小结Advent of TypeScript 2024 第 4 天Christmas Present Delivery Addresses的实质是用一句话概括映射类型的核心价值遍历一个对象类型的所有键为每个键重新指定值类型。通过PresentDeliveryListT这个看似简单的工具类型你实际掌握了泛型参数T如何让工具类型适配任意未知形状的输入keyof T如何产出键联合类型、[K in keyof T]如何驱动逐键映射映射右侧: Address如何实现整体替换属性值类型这一最小但最实用的改写进阶玩法T[K]组合、条件类型联动、as键重映射。借用原文档的收官句式这套语法看似简单但正如仓库的映射类型教程所言它是 TypeScript 最强大、最通用的特性之一——以后写工具类型时你会发现自己频繁求助于它。至于伯纳德但愿他至少从这个有点实际应用的挑战里获得了一点安慰。赞分享教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载相关推荐TypeHero Advent of TypeScript Day 4用泛型映射类型 PresentDeliveryList 批量生成礼物派送地址TypeHero Advent of TypeScript Day 4用泛型映射类型 PresentDeliveryList 批量生成礼物派送地址 本篇文章基教育前端后端scikit-learn 大数据扩展实战基于 out-of-core 增量学习与特征哈希处理超内存数据集scikit learn 大数据扩展实战基于 out of core 增量学习与特征哈希处理超内存数据集 当样本量、特征维度或处理速度超过传统单机内存能容纳的教育前端后端TypeHero Advent of TypeScript 2024 第 8 天用映射类型键重映射与模板字面量类型实现 RemoveNaughtyChildrenTypeHero Advent of TypeScript 2024 第 8 天用映射类型键重映射与模板字面量类型实现 RemoveNaughtyChildr教育前端后端上一篇3步完成超采样替换免费启用帧生成下一篇TiXL 导出独立可执行文件Player完整指南从编辑器到一键分发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考