ARTICLE DETAIL

资讯详情

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

类型体操实战:用模板字面量类型实现 Trim——从 type-challenges 第 108 题看字符串的类型级裁剪

类型体操实战:用模板字面量类型实现 Trim——从 type-challenges 第 108 题看字符串的类型级裁剪 示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载本篇文章围绕 type-challenges 仓库中「去除两端空白字符Trim」这道中等难度题目展开完整还原其解题思路、递归模式匹配原理并结合仓库内的测试用例逐条验证。读完本文你将掌握如何在 TypeScript 类型层面利用模板字面量类型与infer实现字符串裁剪并能独立迁移这套技巧去解决 TrimLeft、TrimRight 等一系列相邻题目。题目速览我们要实现什么题目位于仓库 questions/00108-medium-trim 目录题目难度标记为「中級 / medium」所属主题标签为#template-literal模板字面量类型由 Anthony Fu 提出。需求一句话概括实现TrimT它接收一个精确的字符串类型返回一个删除了两端空白字符的新字符串类型。原题给出的示例type trimmed Trim Hello World // expected to be Hello World也就是说这并非运行时对值的裁剪而是纯粹的类型级compile-time字符串处理输入是字面量字符串类型输出也是经过裁剪后的字面量字符串类型。打开该题目的 template.ts可以看到需要补全的占位实现type TrimS extends string anyS extends string约束了入参必须可赋值给字符串类型我们要做的就是把any替换成真正的递归类型逻辑。前置知识模板字面量类型与 infer 模式匹配要解这道题先掌握两个 TypeScript 的核心能力模板字面量类型Template Literal Types与 JS 的模板字符串语法一致但它作用于类型空间。例如type Greet Hello ${string}表示以 Hello 开头、后接任意字符串的类型。条件类型 infer 模式匹配T extends \${infer Rest} ? ... : ...可以在类型层面把字符串拆开infer 负责捕获其中的一部分。两者结合就能写出类型版的字符串取子串逻辑。仓库 guides 目录下专门收录了相关指南例如 infer 指南 讲解infer在条件类型中的捕获用法递归指南 讲解如何在类型层面进行递归推导本题正是这两种技巧的组合应用。第一步定义空白字符联合类型观察测试用例会发现需要裁剪的空白字符不止空格 还包括换行符\n和制表符\t详见下文测试用例解读。因此先定义一个联合类型type Whitespace | \n | \t这样在后续的模式匹配中${Whitespace}就能一次性匹配三种空白字符中的任意一种。第二步TrimLeft——递归吃掉左侧空白核心思路是只要字符串以空白字符开头就把这个字符剪掉然后对剩余部分继续递归。当不再以空白开头时返回剩余的字符串。type TrimLeftS extends string S extends ${Whitespace}${infer Rest} ? TrimLeftRest : S逐行解读S extends \${Whitespace}${infer Rest}尝试把S匹配为一个空白字符 剩余部分Rest若匹配成功字符串确实以空白开头递归调用TrimLeftRest继续裁剪若匹配失败开头不是空白直接返回S即当前已经左侧干净的字符串。以TrimLeft abc为例递归过程为 abc→ abc→ abc→abc开头为a不再匹配返回。这一思路与仓库中 TrimLeft 题目 完全一致00106 的模板 同样以any占位等待实现。第三步TrimRight——递归吃掉右侧空白对称地裁剪右侧空白就是把匹配模式反过来只要字符串以空白字符结尾就剪掉最后一个字符继续递归。type TrimRightS extends string S extends ${infer Rest}${Whitespace} ? TrimRightRest : S注意这里infer Rest在模板中的位置不同${infer Rest}${Whitespace}表示任意前缀 一个空白字符结尾。递归终止条件是结尾不再是空白字符。以TrimRightabc 为例abc →abc →abc →abc结尾为c返回。仓库中 TrimRight 题目编号 4803作者 Yugang Cao即考察这一对称实现。第四步合体——Trim 组合两侧裁剪TrimT就是先裁剪右侧、再裁剪左侧的组合顺序无影响也可以反过来type TrimS extends string TrimLeftTrimRightS完整可运行的解法如下type Whitespace | \n | \t type TrimLeftS extends string S extends ${Whitespace}${infer Rest} ? TrimLeftRest : S type TrimRightS extends string S extends ${infer Rest}${Whitespace} ? TrimRightRest : S type TrimS extends string TrimLeftTrimRightS也可以把两侧裁剪合并进一个类型直接对左右同时递归type TrimS extends string S extends ${Whitespace}${infer Rest} ? TrimRest : S extends ${infer Rest}${Whitespace} ? TrimRest : S两种写法都能通过题目测试前者更贴近先拆分后组合的模块化思路后者递归次数更少、单类型即可完成。逐条验证对照仓库测试用例该题目的 test-cases.ts 给出了 8 组断言是检验解法正确性的唯一标准。我们逐条模拟输入期望输出TrimLeft 之后TrimRight 之后Trim TrimLeft∘TrimRight 先右后左strstrstrstr strstrstr str→ 左裁 →str strstrstr右裁无变化左裁去 5 个空格 →strstr strstr 右裁去 3 个空格 →str str str右裁 → str左裁 →strstr \n\t foo bar \tfoo bar右裁去\t左裁去 \n\t foo bar \n\t 右裁全吃掉 →注意第 6 条Trim \n\t foo bar \t和第 8 条Trim \n\t 它们专门验证对换行符\n与制表符\t的处理这正是Whitespace联合类型必须包含\n与\t的原因。如果只定义type Whitespace 这两条用例将无法通过。空字符串也是必须覆盖的边界 extends \${Whitespace}${infer Rest}不成立直接返回符合预期。验证机制断言如何工作测试用例中出现了两个辅助类型Expect与Equal它们来自仓库的 utils/index.d.tsexport type ExpectT extends true T export type EqualX, Y (T() T extends X ? 1 : 2) extends (T() T extends Y ? 1 : 2) ? true : falseEqualX, Y通过构造两个函数类型并比较其条件类型结果能够严格判断两个类型是否完全相等比简单的X extends Y更严谨可识别联合类型分配等细微差异ExpectT extends true要求传入的必须恰好是true一旦Equal判定不相等Expect就会产生类型错误从而让类型测试编译失败即测试失败。因此只要把解法填入 template.ts再与 test-cases.ts 一同编译8 组断言全部通过即代表实现正确。递进关系从 TrimLeft 到 Trim 的题型家族这道题在仓库中并非孤立存在而是与相邻题目构成一条清晰的递进链路00106 · TrimLeft只裁剪左侧空白其测试用例如TrimLeft str 期望str 即右侧空白保留——见 00106 的 test-cases.ts00108 · Trim本题左右同时裁剪04803 · TrimRight只裁剪右侧空白其测试如TrimRight str 期望 str——见 04803 的 test-cases.ts。可以发现仓库对这组题目的定位是先用单侧裁剪打基础再组合出双侧裁剪。TrimLeft 题目的说明 与 TrimRight 题目的说明 中也都互相引用了彼此方便读者按递进顺序练习。延伸思考与边界条件为什么不用内置工具类型TypeScript 标准库并没有内置字符串裁剪的工具类型这正是此类类型体操题目的意义所在通过递归与模板字面量类型在类型空间复刻String.prototype.trim的能力用于从字面量类型中提取干净内容如解析路由参数、用户输入标签等场景。空白字符集合可扩展本题只需要空格、换行、制表符三类。若业务中需要处理回车\r、换页\f等字符只需向Whitespace联合类型中追加成员即可递归逻辑无需任何改动。递归深度限制类型级递归受 TypeScript 的递归深度上限约束。对本题常见的短字符串几到几十个字符完全够用若裁剪超长字符串可考虑先裁左再裁右以减少单方向递归次数。infer的位置决定裁剪方向${Whitespace}${infer Rest}裁剪头部${infer Rest}${Whitespace}裁剪尾部——理解这一对称性是吃透整个题型家族的关键也是 infer 指南 强调的核心直觉。小结通过 type-challenges 第 108 题 Trim我们完整实践了模板字面量类型 条件类型 infer 模式匹配 递归这一类型体操黄金组合先以Whitespace联合类型圈定空白字符范围再用递归分别实现左侧、右侧裁剪最后组合出TrimT并通过仓库自带的 8 组测试断言完成验证。这套方法不仅适用于本题也直接延伸至 TrimLeft、TrimRight 以及更广泛的字符串解析类类型设计。赞分享示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载相关推荐Flue 渠道 Webhook 校验机制如何防止伪造事件攻击Flue 渠道 Webhook 校验机制如何防止伪造事件攻击 Flue 是一个面向 AI 智能体的沙箱框架sandbox agent framework人工智能大模型AI AgentAgent 框架工具调用Agent 沙箱MCP Clients告别字符串首尾空格Type Challenges中的Trim类型完全解析告别字符串首尾空格Type Challenges中的Trim类型完全解析 你是否曾在处理用户输入时被意外的空格困扰在TypeScript中如何在编译阶段就示例工程告别字符串处理烦恼Type-Challenges DropChar类型实战指南告别字符串处理烦恼Type Challenges DropChar类型实战指南 你是否还在为TypeScript中字符串处理的复杂类型定义而头疼是否想提升泛示例工程上一篇res-downloader 免抓包下载器教程如何快速下载视频号视频与网页资源下一篇Repomix FAQ 与故障排查完全指南私有仓库、远程打包、Token 削减与 MCP 集成创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表