ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TypeHero Advent of TypeScript 2023 Day 14「Naughty List Decipher」:用模板字面量类型递归实现字符串分割为联合类型

TypeHero Advent of TypeScript 2023 Day 14「Naughty List Decipher」:用模板字面量类型递归实现字符串分割为联合类型 教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载本文是 TypeHero Advent of TypeScriptAOT2023 第 14 天关卡「Naughty List Decipher」的完整实战解析。核心任务是利用 TypeScript 模板字面量类型与infer推断把一个以斜杠分隔的字符串字面量类型如melkey/prime/theo/trash递归拆解为联合类型melkey | prime | theo | trash。读完本文你将掌握类型层面的字符串解析范式并能在实际类型工具库中复用它实现Split、Join等通用工具类型。关卡背景圣诞老人的潦草名单本关卡位于仓库 challenges/aot/2023/14/ 目录其题目与剧情记录在 prompt.md 中。12 月 14 日清晨圣诞老人Santa又一次带着宿醉走进办公室被精灵主管 Bernard 质问今天调皮孩子的名单到底在哪圣诞老人承认名单没丢但只是用斜杠快速草草地记下了名字。于是任务落在我们头上——替圣诞老人收拾烂摊子他给出一份像melkey/prime/theo/trash这样的名单而我们需要把它转成字符串联合类型melkey | prime | theo | trash赶在其余精灵发现之前搞定。任务定义从分隔字符串到联合类型题目要求实现一个名为DecipherNaughtyList的类型工具输入一个由/分隔的字符串字面量类型输出其中所有子串组成的联合类型。初始的待填类型位于 user.tstype DecipherNaughyList unknown;值得一提的是仓库中的初始模板沿用了题目作者留下的拼写DecipherNaughyList缺少字母t而测试中使用的正确名称是DecipherNaughtyList实际解题时需要按测试文件中的名称声明类型。验收标准来自测试文件challenges/aot/2023/14/tests.ts 给出了全部验收用例它们通过type-testing包中的ExpectEqual...工具做严格的类型相等断言import { Expect, Equal } from type-testing; type test_0_actual DecipherNaughtyListtimmy/jimmy; // ^? type test_0_expected jimmy | timmy; type test_0 ExpectEqualtest_0_expected, test_0_actual; type test_1_actual DecipherNaughtyListelliot; // ^? type test_1_expected elliot; type test_1 ExpectEqualtest_1_expected, test_1_actual; type test_2_actual DecipherNaughtyListmelkey/prime/theo/trash; // ^? type test_2_expected melkey | prime | theo | trash; type test_2 ExpectEqualtest_2_expected, test_2_actual;三个用例分别覆盖了三类场景两段分隔timmy/jimmy应得到jimmy | timmy注意联合类型的成员顺序无关紧要无分隔elliot应原样返回elliot这是递归的终止条件多段分隔melkey/prime/theo/trash应得到四个成员组成的联合类型。核心解法模板字面量类型 递归推断解题的关键是 TypeScript 的模板字面量类型Template Literal Types与条件类型中的infer推断。模板字面量类型不仅能拼接字符串还能在extends检查中解构字符串当被检查的类型与${infer Head}/${infer Tail}匹配时Head和Tail会被自动推断为斜杠前后的两个子串。一个满足全部测试的经典实现如下type DecipherNaughtyListT extends string T extends ${infer Head}/${infer Tail} ? Head | DecipherNaughtyListTail : T;逐行拆解泛型约束T extends string确保传入的是字符串类型匹配分支T extends${infer Head}/${infer Tail}当T中存在斜杠时Head取到第一个/之前的片段Tail取到其后的剩余部分。TypeScript 的模板字面量推断默认采用贪婪匹配即Head匹配到第一个/为止递归合并Head | DecipherNaughtyListTail把当前段Head与对剩余部分继续递归的结果合并成联合类型终止分支: T当T中不再有斜杠时直接返回T本身。类型求值过程演示以DecipherNaughtyListmelkey/prime/theo/trash为例编译器逐步展开DecipherNaughtyListmelkey/prime/theo/trash → melkey | DecipherNaughtyListprime/theo/trash → melkey | prime | DecipherNaughtyListtheo/trash → melkey | prime | theo | DecipherNaughtyListtrash → melkey | prime | theo | trash对单个名字elliot由于不满足${infer Head}/${infer Tail}直接落入: T分支返回elliot。边界情况与健壮性加固上面的朴素递归已经能通过全部三个测试但若要把它提升为可复用的通用工具还需要处理两个边界问题1. 空字符串如果输入是朴素实现会返回。空字符串作为联合成员通常不符合预期。可以用T extends ? never : ...把它过滤掉type DecipherNaughtyListT extends string T extends ? never : T extends ${infer Head}/${infer Tail} ? Head | DecipherNaughtyListTail : T;2. 去除空段连续斜杠对于a//b这类连续斜杠的输入Head会推断为空字符串从而混入成员。可把空段也映射为nevertype DecipherNaughtyListT extends string T extends ${infer Head}/${infer Tail} ? (Head extends ? never : Head) | DecipherNaughtyListTail : T extends ? never : T;由于never在联合类型中会被自动吸收T | never恒等于T这个版本能够静默丢弃所有空段。泛化把它升级为通用的 Split 工具类型DecipherNaughtyList本质上是按分隔符拆分为联合类型。把分隔符从写死的/抽成类型参数就得到一个通用的Split工具类型可以复用于解析逗号列表、路径片段、CSV 表头等场景type SplitS extends string, D extends string S extends ${infer Head}${D}${infer Tail} ? Head | SplitTail, D : S;例如type Keys Splitid,name,email, ,; // 结果id | name | email注意这里的分隔符D也可以是字符串字面量类型如::这样的多字符分隔符这是模板字面量类型在模式匹配上的灵活性体现。仓库中的挑战结构与验证机制要理解这个关卡如何被验收可以查看整个挑战仓库的组织方式与校验脚本。挑战目录约定每个挑战目录都包含标准化的五个文件以 challenges/aot/2023/14/ 为例文件作用prompt.md题目剧情与任务描述user.ts参与者需要填写的初始模板tests.ts基于type-testing的Expect/Equal断言tsconfig.json该挑战独立的编译选项metadata.json关卡元数据id、label、difficulty、author等其中 metadata.json 的内容为{ id: 2023-14, label: Day Fourteen, description: Day fourteen of Advent of Typescript, difficulty: event, prerequisites: [], author: TypeHero }可见 AOT 作为年度活动所有关卡的difficulty统一为event且本关没有前置关卡prerequisites为空。这些字段的取值约束定义在 challenges/aot/metadata.schema.json 的 JSON Schema 中。验证脚本如何工作仓库根目录的 challenges/validate.ts 是全部挑战的校验中枢它会做两件事元数据校验检查每个目录都有metadata.json与tsconfig.json、目录名与id一致、prerequisites指向真实存在的关卡等类型级测试对每个挑战将solutions/下的解答文件与tests.ts拼接在内存中通过 TypeScript Compiler APIcreateProgramgetPreEmitDiagnostics编译收集所有类型错误并逐一输出✓/✗。这也解释了为什么解答被存放在solutions/目录validate.ts会遍历该目录下所有以数字命名的.ts文件如1.ts把每个解答与测试一同编译验证。本关的 solutions/1.ts 目前是空白文件等待参与者填入实现。当前关卡的 tsconfig.json 开启了strict、exactOptionalPropertyTypes与noUncheckedIndexedAccess解答需在这些严格选项下保持零类型错误。知识点小结与延伸本关虽短却浓缩了三个重要的 TypeScript 类型编程技巧模板字面量类型可以做模式匹配${infer Head}/${infer Tail}让字符串字面量类型具备了可解构能力是类型层字符串解析的基础递归 联合类型 类型层循环类型系统没有for循环一切重复操作都依赖条件类型的递归展开而联合类型天然具备去重与吸收never成员自动消失的特性非常适合作为递归的累加容器ExpectEqual...是类型级测试的事实标准type-testing包的这一对工具把类型是否相等变成可编译校验的断言TypeHero 的全部挑战包括本关都以此验收。有趣的是同样的挑战在 challenges/aot/2024/14/tests.ts 中原封不动地再次出现——可见把斜杠名单解析成联合类型已成为 AOT 系列中一个经典的教学关卡。如果你希望更系统地练习这类字符串工具类型仓库中还有 literal-types、type-unions、typeof 等配套关卡可供循序进阶挑战编写规范可参考 challenges/challenge-guidelines.md。赞分享教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载相关推荐TypeHero Advent of TypeScript 2024 第 14 天用模板字面量类型实现 DecipherNaughtyList把字符串拆成联合类型TypeHero Advent of TypeScript 2024 第 14 天用模板字面量类型实现 DecipherNaughtyList 把字符串拆成教育前端后端TypeHero 挑战解析用 TypeScript 模板字面量类型把字符串渲染成 ASCII ArtAdvent of TypeScript 2023 · Day 20TypeHero 挑战解析用 TypeScript 模板字面量类型把字符串渲染成 ASCII ArtAdvent of TypeScript 2023 ·教育前端后端TypeHero Advent of TypeScript 2023 第 1 天实战用字面量联合类型定义 SantasFavoriteCookiesTypeHero Advent of TypeScript 2023 第 1 天实战用字面量联合类型定义 SantasFavoriteCookies 本篇以教育前端后端上一篇ImageBind音频处理技术揭秘如何将声音转化为通用嵌入向量下一篇POCO多线程性能调优团队协作角色与流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表