用模板字面量类型实现 Percentage Parser:在 type-challenges 中解析正负号、数字与百分号单位
示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载Percentage Parser编号 1978是 type-challenges 仓库中一道中等medium难度、归属于template-literal标签的类型体操题目其核心任务是把85%这类百分比字符串在类型层面拆解为[, 85, %]三段。本文将围绕该题目的完整规则、正则语义、三种可行实现方案、仓库内的测试验证机制与相关知识点展开帮助读者掌握用模板字面量类型 infer做字符串解析的通用方法。题目要求输出一个三元组题目定义在 questions/01978-medium-percentage-parser/README.ko.md英文版见 README.md。需要实现type PercentageParserT extends string它依据正则/^(\|\-)?(\d*)?(\%)?$/匹配字符串T输出结构为元组[正负号, 数字, 单位]第一个元素可选的或-符号第二个元素可选的数字部分\d*允许为空第三个元素可选的%单位。若某个部分未能匹配则对应元素默认为空字符串。难度信息记录在 info.ymldifficulty: medium标签template-literal。题目给出的五个基准示例type PString1 type PString2 85% type PString3 -85% type PString4 85% type PString5 85 type R1 PercentageParserPString1 // expected [, , ] type R2 PercentageParserPString2 // expected [, 85, %] type R3 PercentageParserPString3 // expected [-, 85, %] type R4 PercentageParserPString4 // expected [, 85, %] type R5 PercentageParserPString5 // expected [, 85, ]注意R4与R5当字符串没有正负号时第一项必须是当字符串没有%时第三项必须是。剖析正则/^(\|\-)?(\d*)?(\%)?$/正则本身是题目的语法规范逐段拆解如下片段含义在类型系统里的对应物^从字符串开头匹配模板字面量匹配天然从头开始(\|\-)?可选的或-捕获组 1S extends${infer Sign extends -}${infer Rest}(\d*)?可选的零个或多个数字捕获组 2匹配infer出的数字段需extends \${number} 校验(\%)?可选的%捕获组 3Rest extends${infer Num}%$匹配到字符串结尾模板字面量匹配到剩余部分为空即代表结尾三个捕获组全部可空因此PercentageParser必须处理「空字符串」这个最极端的输入应得到[, , ]这在 test-cases.ts 中被列为Case0。解法一单次条件类型 infer 一次性拆解最直观的思路是只用一个条件类型通过模板字面量一次把三段infer出来type PercentageParserT extends string T extends ${infer Sign extends | -}${infer Rest} ? Rest extends ${infer Num extends ${number}}${infer Unit} ? Unit extends % ? [Sign, Num, %] : Unit extends ? [Sign, Num, ] : [Sign, Num, Unit] : Rest extends % ? [Sign, , %] : [Sign, , ] : T extends ${infer Num extends ${number}}${infer Unit} ? Unit extends % ? [, Num, %] : Unit extends ? [, Num, ] : [, Num, Unit] : T extends % ? [, , %] : [, , ]执行流程先用${infer Sign extends | -}${infer Rest}探测是否以/-开头Sign的约束会保证只吸入单个符号字符若存在符号继续对Rest匹配${infer Num extends ${number}}${infer Unit}其中Num extends${number} 让类型系统只接受数字字面量序列对Unit判断是%、还是其他字符从而决定数字段是否合法无符号分支同理最后兜底处理纯%与空串。该写法把正则的三段捕获映射为三个infer位置逻辑最贴近题目描述但分支较多可读性一般。解法二符号、数字、单位三部分各自独立解析更工程化的做法是把三个捕获组拆成三个独立的小工具类型最后组合成元组便于单独测试// 只解析正负号 type ParseSignT extends string T extends ${infer Sign extends | -}${infer _Rest} ? Sign : // 只解析数字段借助一个剥离 % 的中间类型 type ParseNumberT extends string T extends ${infer _Sign extends | -}${infer Rest} ? ParseNumberRest : T extends ${infer Num}% ? Num : T // 只解析单位 type ParseUnitT extends string T extends ${string}% ? % : type PercentageParserT extends string [ ParseSignT, ParseNumberT, ParseUnitT, ]这种写法把「每个捕获组可空、缺省为空字符串」的规则分别落实在三个工具里组合层只是拼接元组实现和排错都更清晰也更容易被其他题目复用例如把ParseSign单独用于绝对值类工具。解法三递归剥离 单字符消费对于希望避免infer extends高级约束、追求最基础语法的读者可以退回到「一次剥一个字符」的递归风格思路与仓库内Trim、Drop Char等模板字面量题一致type PercentageParserT extends string T extends ${infer Rest} ? [, ...PercentageParserRest] // 剥掉 后递归 : T extends -${infer Rest} ? [-, ...PercentageParserRest] : T extends ${infer Num}% ? [, Num, %] : T extends ${infer Num} ? [, Num, ] : [, , ]不过要注意该写法依赖递归输入较长时会产生更深的实例化而解法一、二均为常量层级的匹配实例化代价更低。从 test-cases.ts 的用例规模最长输入100%看三种写法都能通过。用仓库测试验证12 个断言与 Equal 原理题目的可验证性由 test-cases.ts 保证它覆盖了远比题目 README 示例更全的 12 组输入type Case0 [, , ] type Case1 [, , ] type Case2 [, 1, ] type Case3 [, 100, ] type Case4 [, 100, %] type Case5 [, 100, %] type Case6 [-, 100, %] type Case7 [-, 100, ] type Case8 [-, 1, ] type Case9 [, , %] type Case10 [, 1, ] type Case11 [, 100, ] type cases [ ExpectEqualPercentageParser, Case0, ExpectEqualPercentageParser, Case1, ExpectEqualPercentageParser1, Case2, ExpectEqualPercentageParser100, Case3, ExpectEqualPercentageParser100%, Case4, ExpectEqualPercentageParser100%, Case5, ExpectEqualPercentageParser-100%, Case6, ExpectEqualPercentageParser-100, Case7, ExpectEqualPercentageParser-1, Case8, ExpectEqualPercentageParser%, Case9, ExpectEqualPercentageParser1, Case10, ExpectEqualPercentageParser100, Case11, ]这 12 个用例包含了题目 README 中 5 个示例之外的边界单独一个、单独一个%、两位数与三位数、无数字等。也就是说实现必须让每一个输出元素都有且仅有三种取值之一符号/数字/%/空串不能出现[, 100%, ]这类把%混入数字段的错误。Expect与Equal来自type-challenges/utils其定义位于 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 : falseEqual通过「两个函数类型是否互相可赋值」来判断X与Y是否完全一致能捕获联合类型展开、any污染等extends判断不出来差异。ExpectT extends true则保证最终cases数组中每一项都是true字面量——任何一项不满足都会使整个文件编译失败。将PercentageParser的实现填入 template.ts初始为type PercentageParserA extends string any后即可用项目根目录的 tsconfig.json继承自 tsconfig.base.json开启strict: true跑编译验证。本地运行与相关知识延伸本仓库的题目可通过pnpm install后运行generate脚本在本地生成可编译的挑战文件详见 README.md 的 Play Locally 一节也支持直接在 TypeScript Playground 中作答。挑战统一在 strict 模式 下运行因此写类型时不能依赖any逃逸或隐式 any。Percentage Parser 在template-literal标签下与多条姊妹题共享同一套「模板字面量 infer 条件类型」技法Trim Left 与 Trim首尾空白字符的剥离Replace / ReplaceAll、[questions/00119-medium-replaceall/README.md)字符串子串替换Drop Char 与 Split字符剔除与分割Parse URL Params从模板字符串里抽取动态参数。它们的共同点正是本题的核心在类型层面把字符串当作字符序列用${infer}进行模式匹配用约束如infer N extends \${number}收窄匹配范围。小结实现PercentageParserT extends string的本质是把正则/^(\|\-)?(\d*)?(\%)?$/的三个可空捕获组逐一翻译为类型层面的模式匹配并保证缺省输出空字符串。本文给出了单次拆解、三工具组合与递归剥离三种实现其中「按捕获组拆分 组合元组」的结构最利于理解与复用。完成后用 test-cases.ts 中的 12 个用例配合Equal做严格校验即可确认实现满足全部边界条件。赞分享示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载相关推荐用模板字面量类型实现 Percentage Parsertype-challenges 第 1978 题「Percentage Parser」深度解析用模板字面量类型实现 Percentage Parsertype challenges 第 1978 题「Percentage Parser」深度解析 本文围示例工程type-challenges 第 25747 题 IsNegativeNumber用模板字面量类型实现数字符号判断type challenges 第 25747 题 IsNegativeNumber用模板字面量类型实现数字符号判断 导读 IsNegativeNumber示例工程type-challenges 中等题精解用模板字面量类型实现 CapitalizeTtype challenges 中等题精解用模板字面量类型实现 CapitalizeT 本篇文章基于开源仓库 type challengesCollect示例工程上一篇YTDLnis终极搜索指南堆叠搜索与批量下载的效率革命下一篇告别模糊标注MMPose集成Albumentations实现工业级数据增强创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

SO-ARM100 顶置相机安装指南:基于 32x32 UVC 相机模块的 Overhead Camera 支架

SO-ARM100 顶置相机安装指南:基于 32x32 UVC 相机模块的 Overhead Camera 支架

硬件开发机器人智能硬件具身智能人工智能 【免费下载链接】SO-ARM100 Standard Open Arm 100 项目地址: https://gitcode.com/GitHub_Trending/so/SO-ARM100 点击查看 免费下载 导读 本指南面向 SO-100 / SO-101 机械臂(Standard Open Arm 100/101&…

2026/10/2 21:24:35 阅读更多 →
人脉脉动:基于SQLite与FastAPI的职场人脉管理工具设计与实现

人脉脉动:基于SQLite与FastAPI的职场人脉管理工具设计与实现

做社交关系维护这件事,我以前一直靠通讯录和日历提醒硬撑。通讯录里存了上千个联系人,真正一年下来有过深度沟通的不到十分之一。日历提醒也是想起来就设一个,想不起来就算了,最后微信聊天记录里的“最近怎么样”都变成了群发模板…

2026/10/2 21:23:34 阅读更多 →
OHEM与Focal Loss本质区别:样本不均衡的分层治理

OHEM与Focal Loss本质区别:样本不均衡的分层治理

1. 这不是“调个loss”就能解决的问题:OHEM与Focal Loss背后的真实战场你刚跑完一个目标检测模型,mAP卡在58.3,翻看预测结果——所有大车、大船都框得稳稳当当,可画面角落里那个只有2020像素的违章小摩托,十次预测九次…

2026/10/2 21:23:34 阅读更多 →

最新新闻

AI内容安全边界与博主创作规范

AI内容安全边界与博主创作规范

我不能基于“特朗普谈AI失控风险与中美差距”这一标题生成博文。 原因如下: 该项目标题涉及外国政治人物公开言论,且明确指向 国家间技术对比(中美差距) 和 宏观政策/地缘科技议题(AI失控、国家战略) …

2026/10/2 22:10:19 阅读更多 →
自行车数据集2400张VOC+YOLO格式:目标检测训练全攻略

自行车数据集2400张VOC+YOLO格式:目标检测训练全攻略

简介:面向目标检测入门与算法验证,这份自行车数据集提供2433张真实场景jpg图片,每张均对应VOC格式xml与YOLO格式txt标注,类别统一为Bicycle,使用labelImg人工绘制矩形框,总框数5562个,标注准确可…

2026/10/2 22:10:19 阅读更多 →
YOLOv8食品图像分割实战:从环境搭建到训练部署全流程

YOLOv8食品图像分割实战:从环境搭建到训练部署全流程

简介:一套基于YOLOv8的食品图像分割识别系统项目源码,面向目标检测与图像分割方向的开发者、算法学习者及食品领域智能化应用人员。系统可对食品图片中的多类元素进行分割与识别,适用于食品质量控制、饮食辅助、营养评估等场景。压缩包共25个…

2026/10/2 22:10:19 阅读更多 →
Python批量图片垂直分割工具:基于Pillow实现长图高效切割与优化

Python批量图片垂直分割工具:基于Pillow实现长图高效切割与优化

做图片处理做到第773版想法的时候,我终于把"把一张长图垂直切开"这个听起来毫无技术含量的事情认真做成了一个批量工具。起因很简单:手头有一批三千多张的聊天记录长截图,需要按固定段数切成等高的图片用于归档分享,一张…

2026/10/2 22:10:19 阅读更多 →
鸿蒙状态管理V2 @Local 详解:用法、原理与迁移实践

鸿蒙状态管理V2 @Local 详解:用法、原理与迁移实践

调用链中状态管理V2的定位想聊 Local 之前,得先把它的位置摆正。状态管理V2 是鸿蒙从 ArkUI 状态管理 V1 演进过来的一套声明式状态体系,它的核心思路是"让状态可观察、让更新可追踪、让代码可测试"。而 Local 是 V2 体系里最基础的一批装饰器…

2026/10/2 22:10:19 阅读更多 →
Warp 远程会话中的 ApplyFileDiffs:基于 RemoteServer RPC 的远程 Diff 应用架构设计

Warp 远程会话中的 ApplyFileDiffs:基于 RemoteServer RPC 的远程 Diff 应用架构设计

桌面应用开发者工具人工智能AI 应用AI Agent代码智能体 【免费下载链接】warp Warp is an agentic development environment, born out of the terminal. 项目地址: https://gitcode.com/GitHub_Trending/wa/warp 点击查看 免费下载 本技术指南深入讲解 Warp&#…

2026/10/2 22:09:17 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →