type-challenges 中等题 02257:用类型体操实现 MinusOne(正整数减一)
示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载导读MinusOne是 type-challenges 仓库中一道medium 难度、math 标签的类型体操题给定一个正整数作为类型参数要求返回该数字减一后的字面量类型。本文以 questions/02257-medium-minusone/README.md 为骨架结合仓库中的测试用例与工具库源码讲解题目约束、测试边界、多种解题思路元组计数、字符串解析等并给出本地运行与验证测试的方法。读完后你将掌握“用纯类型系统表达算术运算”的核心套路为后续更复杂的Sum、Multiply等极端题目打下基础。题目速览原题描述非常简洁README.mdGiven a number (always positive) as a type. Your type should return the number decreased by one.即输入恒为正整数输出其减一的结果。题目给出的两个示例type Zero MinusOne1 // 0 type FiftyFour MinusOne55 // 54仓库中对应的起始模板位于 template.ts需要实现的部分只有一个类型占位符type MinusOneT extends number any题目元数据记录在 info.yml难度medium标签math作者为 Mustafo FaizGitHub: fayzzzm。测试用例隐藏在细节里的边界条件题目能否通过完全取决于仓库中的测试文件 test-cases.ts。它通过type-challenges/utils提供的Equal与Expect工具来断言类型相等import type { Equal, Expect } from type-challenges/utils type cases [ ExpectEqualMinusOne1, 0, ExpectEqualMinusOne55, 54, ExpectEqualMinusOne3, 2, ExpectEqualMinusOne100, 99, ExpectEqualMinusOne1101, 1100, ExpectEqualMinusOne9_007_199_254_740_992, 9_007_199_254_740_991, ]逐条拆解这些用例能提炼出题目的真实约束个位数MinusOne1 0。注意结果可以是 0因此实现必须覆盖 1 → 0 的退化情况类型层面的“借位”。多位数普通情形55 → 54、3 → 2、100 → 99覆盖十位、个位与整百借位。四位数1101 → 1100验证多位数字符串/数组的处理正确性。最大安全整数边界9_007_199_254_740_992 → 9_007_199_254_740_991。9_007_199_254_740_992正是2^53是 JSNumber的最大安全整数Number.MAX_SAFE_INTEGER 1。这个用例直接封死了“用元组长度做算术”的朴素做法见下文是本题的题眼。Equal的严格语义定义在 utils/index.d.ts它通过函数参数类型的逆变比较来区分any、联合类型等细微差异也就是说你的实现不能返回any或number必须是精确的字面量类型。思路一元组长度计数直观但会“爆栈”类型体操中最直观的“数数”工具是元组T[length]可以取出一个元组类型的长度。于是有人会构造“长度为 N 的元组”再取“去掉最后一个元素后剩下的元组长度”type BuildTupleN extends number, R extends unknown[] [] R[length] extends N ? R : BuildTupleN, [...R, unknown] type MinusOneT extends number BuildTupleT extends [...infer Rest, unknown] ? Rest[length] : never它通过递归把数字“翻译”成元组再用infer Rest剥离最后一个元素。但这份实现有一个致命问题类型递归深度和元组展开规模都受编译器限制。对于T 55、100尚可一旦遇到测试中的1101甚至9_007_199_254_740_992元组根本无法实例化必然产生Type instantiation is excessively deep之类的编译错误。这也是为什么这道题被标为 medium 而非 easy——难点恰恰在于必须绕过朴素的元组计数。思路二字符串模板字面量 借位算法推荐绕开元组的思路是先把数字T转成字符串类型通过模板字面量类型infer逐位解析实现类似小学数学的“借位减法”。一个可行的高层骨架如下type MinusOneT extends number DigitMinusOne${T} // 核心对字符串表示的数字执行减一返回字符串 // 逐位处理末位末位非 0 直接减末位为 0 则借位并把前段递归减一 type DigitMinusOneS extends string S extends ${infer Rest}${0} ? ${DigitMinusOneRest}9 // 末位是 0向前借位末位变 9 : S extends ${infer Rest}${infer Last} ? ${Rest}${DecrementDigitLast} // 末位非 0直接对该位减一 : never // 0~9 的查表把单个字符减一1 - 0…9 - 8 type DecrementDigitD extends string D extends 1 ? 0 : D extends 2 ? 1 : D extends 3 ? 2 : D extends 4 ? 3 : D extends 5 ? 4 : D extends 6 ? 5 : D extends 7 ? 6 : D extends 8 ? 7 : D extends 9 ? 8 : never处理逻辑可拆解为末位非 0直接查DecrementDigit表把末位减一其余前缀保持不动如1101→ 前缀110 末位1→01100。末位为 0需要“借位”——前缀部分递归执行减一末位补成9如100→DigitMinusOne10 999。递归出口当字符串只剩一个字符且为1时查表得到0但要注意1的再前缀为空的情况DigitMinusOne需要额外处理避免infer匹配失败。需要注意这类基于字符串的解法在数字较大时只增加类型实例化的节点数而非递归深度只要单次模板匹配的深度可控就能覆盖9_007_199_254_740_992这样的用例。实际调试时可用 IDE 的// ts-expect-error或临时type Check ...断言逐个验证子类型。思路三长度归一化与“数组缩放”更高级的替代路径由于测试用例存在2^53这个天文数字另一种可行方向是避开逐位大数处理利用数字的二进制/可分解结构把大数拆成可被元组容纳的小块再分别减一。典型做法把T拆成10^k的倍数与余数利用T A * 10 B的形式通过BuildTupleA只构造“商”级别的元组借助MinusOne递归作用在“高位移位后的商”上最终拼接回结果。这类方案通常还会配合T[length] extends的守卫例如T extends 1 ? 0 : ...先处理最小退化情形再用映射类型或递归分支把大数“缩放”到元组可实例化的规模。实现上需要更精细地控制递归深度是进阶玩家研究这道题时喜欢钻研的方向。仓库中没有预置标准答案读者可以自行验证上述任一思路能否通过 test-cases.ts 的全部断言。如何在本地运行与验证仓库根目录使用 pnpm 管理见 package.json 的packageManager: pnpm8.12.1测试工具与类型断言库都在type-challenges/utils实现见 utils/index.d.ts。你可以按以下步骤本地验证# 1. 安装依赖仓库已提供 pnpm-workspace.yaml pnpm install # 2. 在 template.ts 中填入你的 MinusOne 实现 # 3. 用 tsc 对 test-cases.ts 做类型检查tsconfig 见 tsconfig.base.json # lib 为 ESNext支持模板字面量类型与 _ 数字分隔符 pnpm exec tsc --noEmit questions/02257-medium-minusone/test-cases.ts若test-cases.ts中 6 条ExpectEqual...全部通过且无类型错误即代表实现正确。注意 tsconfig.base.json 开启了strict模式noUnusedParameters为true编写辅助类型时需留意未使用参数的处理。为什么“减一”值得单独一道题MinusOne虽然只是“减一”但它把类型体操中的三大核心能力串联在了一起递归类型无论元组递归还是字符串借位递归都依赖条件类型 递归展开模板字面量类型${T}把数字变成可逐位解析的字符串是处理任意长度数字的关键武器infer模式匹配S extends${infer Rest}${infer Last} 这类模式是解析结构的标准姿势。它是通往Sum、Subtract、Multiply等更高阶 math 题如仓库中 00476-extreme-sum、00517-extreme-multiply的敲门砖。理解“元组计数的天花板”与“字符串借位的替代方案”这两条路线对后续几乎所有数值类挑战都有直接迁移价值。小结MinusOne的表面要求只有一句话——正整数减一但 test-cases.ts 中的2^53用例决定了朴素元组计数不可行。推荐的解题路线是把数字转成模板字面量字符串逐位做借位减法进阶路线则是利用数字分解把大数“缩放”到元组可处理的规模。结合 utils/index.d.ts 中Equal的严格语义最终返回的必须是精确的字面量类型。沿着 README.zh-CN.md 与仓库根目录的 README.md 可以继续挑战同一 math 序列的其他题目。赞分享示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载相关推荐TypeScript 类型体操用纯类型系统实现大数乘法 Multiplytype-challenges 517TypeScript 类型体操用纯类型系统实现大数乘法 Multiplytype challenges 517 导读 本指南围绕 type challen示例工程type-challenges 中等题精讲用类型体操实现 Diff取出两个对象类型之间的差值属性type challenges 中等题精讲用类型体操实现 Diff取出两个对象类型之间的差值属性 导读 本文讲解 type challenges 仓库中编号示例工程type-challenges 中等题解用 TypeScript 类型系统实现 Diff 对象差集type challenges 中等题解用 TypeScript 类型系统实现 Diff 对象差集 导读 本文深入解析 type challenges 题库第示例工程上一篇CertD企业级SSL证书自动化管理的终极解决方案下一篇像素地牢深度解析如何从零掌握这款开源Roguelike神作创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Art Design Pro 快速上手:Vue 3 + Vite + TypeScript 后台管理模板的安装、精简与开发实战指南

Art Design Pro 快速上手:Vue 3 + Vite + TypeScript 后台管理模板的安装、精简与开发实战指南

前端企业应用UI组件 【免费下载链接】art-design-pro A Vue 3 admin dashboard template using Vite TypeScript Element Plus | vue3 admin | vue-admin — focused on user experience and visual design. 项目地址: https://gitcode.com/GitHub_Trending/ar/ar…

2026/10/2 17:55:57 阅读更多 →
递推最小二乘法RLS:公式推导、遗忘因子与工程实现要点

递推最小二乘法RLS:公式推导、遗忘因子与工程实现要点

/* 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 17:54:57 阅读更多 →
2026本地部署大模型实战指南:工具选型、硬件适配与生产落地

2026本地部署大模型实战指南:工具选型、硬件适配与生产落地

1. 为什么“本地部署大模型”不再是极客玩具,而成了刚需?2026年,如果你还在把大模型当作必须联网调用的云端黑箱,那你的工作流可能已经落后了至少两个迭代周期。这不是危言耸听——上周我帮一家做工业质检的客户做方案评审&#x…

2026/10/2 17:54:57 阅读更多 →

最新新闻

Git指令实战:从配置、分支合并到撤销回滚的完整指南

Git指令实战:从配置、分支合并到撤销回滚的完整指南

很多人对Git敬而远之,是因为感觉它指令太多、太抽象。我当年学Git也是靠死记硬背,背一个用一个是常态,直到有一次在分支合并时把代码搞得一团糟,push又被远端拒绝,大半夜对着终端发呆,才真正想明白&#xf…

2026/10/2 18:27:15 阅读更多 →
开源平替版Claude Cowork实测:多智能体任务编排与部署避坑指南

开源平替版Claude Cowork实测:多智能体任务编排与部署避坑指南

最近圈子里聊得最凶的,除了各家大模型轮番更新,就是 Claude Cowork 这个功能了。官方放出来之后确实惊艳——让 Claude Code 当“老板”,自己拆任务、招“员工”、并行干活,整个就是一个 AI 虚拟团队。但问题也很现实:…

2026/10/2 18:27:15 阅读更多 →
FreeCAD MCP 源码拆解:GUI 线程分发机制,让 RPC 安全驱动 CAD 主线程

FreeCAD MCP 源码拆解:GUI 线程分发机制,让 RPC 安全驱动 CAD 主线程

FreeCAD MCP 源码拆解:GUI 线程分发机制,让 RPC 安全驱动 CAD 主线程 【免费下载链接】freecad-mcp FreeCAD MCP(Model Context Protocol) server 项目地址: https://gitcode.com/gh_mirrors/fr/freecad-mcp FreeCAD MCP 是一个让 AI(…

2026/10/2 18:27:15 阅读更多 →
企业微信智能办公革命:OpenClaw对接全攻略与TaoToken统一通道配置

企业微信智能办公革命:OpenClaw对接全攻略与TaoToken统一通道配置

/* 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 18:27:15 阅读更多 →
CentOS Stream 9 根分区在线扩容指南:LVM操作全流程

CentOS Stream 9 根分区在线扩容指南:LVM操作全流程

1. 开始之前:先搞懂为什么要在线扩容根分区 前几天我手上一台CentOS Stream 9的测试机又报警了, df -h 一看根分区用了97%,日志一查全是容器镜像和依赖包撑爆的。这种事在真实服务器上太常见了,尤其是那些一开始只给根分区分了5…

2026/10/2 18:27:15 阅读更多 →
Google Play支付后端必看:service account.json获取与对接指南

Google Play支付后端必看:service account.json获取与对接指南

做Google Play支付的时候,最让后端同学头疼的往往不是写代码,而是搞到那把能进Google Play Developer API的钥匙。标题里说的service account.json就是这个钥匙。很多团队在客户端把谷歌支付集成了,订单也生成了,结果后端要验签、…

2026/10/2 18:26:15 阅读更多 →

日新闻

从零搭建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 阅读更多 →