)
教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载本篇技术指南围绕 TypeHero 仓库中 Advent of TypeScript 2024 第 22 天挑战题Reindeer Sudoku展开题目要求读者仅凭类型层面编写一个名为Validate的谓词类型predicate判断一个用 9 种驯鹿 emoji 填满的 9×9 数独棋盘是否符合行、列、宫三大约束。读完本文你将掌握如何在 TypeScript 类型系统中用元组tuple、递归条件类型与字符串字面量类型实现复杂的矩阵校验并理解 TypeHero 挑战题的题目—用户骨架—测试断言—校验脚本完整链路。挑战背景驯鹿的恶作剧圣诞老人的九只驯鹿——Dasher、Dancer、Prancer、Vixen、Comet☄️、Cupid❤️、Donner️、Blitzen⚡和 Rudolph——这次决定把自己排列成一块数独棋盘来捣乱。它们在开摆之前还给圣诞老人留下一段预言式的消息SaNtA.... yOu MuSt ImPleMeNt ThEValidateTyPe To DeTerMinE WhEThEr OuR SuDokU ConFiGuRaTiOn Is vALid更贴心的是Vixen 还单独留了一张字条make sureValidateis a predicateVixen这里的 predicate谓词是计算机科学中对返回true或false的函数的称呼。放到类型层面这意味着Validate必须是一个条件类型conditional type对合法棋盘解析为字面量类型true对非法棋盘解析为false而不是boolean这种宽泛联合。这一点在 tests.ts 中通过Equaltest_sudoku_x_actual, true | false形式的严格断言得到了强制。Sudoku 规则回顾题目在 prompt.md 中完整复述了数独的经典规则网格结构游戏在 9×9 的网格上进行网格被划分为九个 3×3 的子网格即宫region。数字填充目标是用 1 到 9 的数字填满整个网格。行约束每一行必须包含 1 到 9 的每个数字不得重复。列约束每一列也必须包含 1 到 9 的每个数字不得重复。宫约束九个 3×3 的宫各自必须包含 1 到 9 的每个数字同样不得重复。通常玩家需要通过逻辑推演填出空格确保行、列、宫都满足规则而本题反其道而行——所有格子已经全部填满我们的任务只是判断给定配置是否符合数独规则即从求解变成验证。题目给出的类型骨架挑战目录 challenges/aot/2024/22 下包含五个关键文件其中 user.ts 预先声明了九只驯鹿的类型别名及其语义注释/** because dashing implies speed */ type Dasher ; /** representing dancing or grace */ type Dancer ; /** a deer, prancing */ type Prancer ; /** a star for the dazzling, slightly mischievous Vixen */ type Vixen ; /** for the celestial body that shares its name */ type Comet ☄️; /** symbolizing love, as Cupid is the god of love */ type Cupid ❤️; /** representing thunder, as Donner means thunder in German */ type Donner ️; /** meaning lightning in German, hence the lightning bolt */ type Blitzen ⚡; /** for his famous red nose */ type Rudolph ; type Reindeer | Dasher | Dancer | Prancer | Vixen | Comet | Cupid | Donner | Blitzen | Rudolph;每个 emoji 与驯鹿的名字一一对应例如 Donner 在德语中意为雷故用 ️Blitzen 在德语中意为闪电故用 ⚡因此Reindeer联合类型恰好有 9 个成员——这为后续每种符号恰好出现一次的去重校验提供了天然基础。待实现的核心类型是一个占位符type Validate unknown;你需要把它替换成自己的实现。注意题目的语义是验证棋盘是否合法即Validate接收一个 9×9 的 emoji 矩阵并作为谓词返回true或false。测试断言六个棋盘三对三错tests.ts 定义了 6 个测试用例前 3 个断言Validate...等于true后 3 个断言等于false。它们通过type-testing包中的Equal与Expect工具进行严格相等检查import { Equal, Expect } from type-testing; type test_sudoku_1_actual Validate[ [[, , ], [☄️, ❤️, ️], [, ⚡, ]], [[, ⚡, ], [, , ], [☄️, ❤️, ️]], // ...共 9 行 ]; type test_sudoku_1 ExpectEqualtest_sudoku_1_actual, true;逐用例分析可以提炼出验证器必须能识别的非法模式test_sudoku_1/2/3期望true三个棋盘均为合法解。以 test_sudoku_1 为例它是标准的三行一循环拉丁方结构每 3 行一个宫行块符号在块内轮转行、列、宫全部无重复。test_sudoku_4期望false与 test_sudoku_1 几乎完全相同但第 7 行第 3 列的符号从被篡改为见 tests.ts 第 53 行。这直接导致第 7 行内重复、第 3 列内重复且右下角宫第 7~9 行、第 7~9 列出现两个——一个改动同时触发三条约束违规。test_sudoku_5期望false与 test_sudoku_2 几乎相同但第 7 行的第三个元素从被改成第 67 行使该行出现两个。test_sudoku_6期望false一个明显更混乱的棋盘例如第 1 行就出现两次、一次且第 4 行第 1 列与第 5 行第 5 列等位置存在跨行重复说明验证器必须同时检查行、列、宫三个维度任何单维度校验都放不过这些用例。从测试结构看合法的正样本大多采用同一宫行块内三个宫为同一符号三元组的轮换排列这暗示一个高效的实现思路每个宫恰好是某组三个符号的全排列且每个宫行块与宫列块内部保持轮换。但更通用、更稳妥的做法是显式校验三大约束见下文。核心解题思路类型级三大约束校验Validate的输入是T extends Reindeer[][]9 行 × 9 列每行 9 个元素总长 81。在类型系统里实现数独验证可以拆成三个相互独立的工具类型然后取与1. 行校验检查每行无重复把一行长度为 9 的元组的所有元素做去重再比较去重前后长度是否一致type ToUnionT extends unknown[] T[number]; type HasDuplicatesT extends unknown[] EqualToUnionT, T[0] extends true ? false // 单元素或空行不可能重复 : /* 用递归逐行拆分判断 */ ...; type AllRowsUniqueT extends Reindeer[][] T extends [infer Head extends Reindeer[], ...infer Tail extends Reindeer[][]] ? RowIsUniqueHead extends true ? AllRowsUniqueTail : false : true;这里的核心技巧是借助元组联合去重后长度是否变短或逐一弹出元素并检查剩余部分是否仍包含该元素来判断重复。例如一个通用的无重复判定可以写成type HasDupT extends unknown[], Acc extends unknown[] [] T extends [infer Head, ...infer Tail] ? Head extends Acc[number] ? true : HasDupTail, [...Acc, Head] : false;2. 列校验先转置再复用行校验类型系统没有直接的按列取值语法但可以定义一个Transpose工具类型把 9×9 矩阵转置成 9×9第 i 行变为原第 i 列随后对转置结果复用AllRowsUniquetype TransposeM extends Reindeer[][] { [I in keyof M]: { [J in keyof M]: M[J][I] } };其中keyof M产生的0 | 1 | ... | 8索引键会在映射类型中被逐一实例化从而完成行列互换。3. 宫校验重塑为宫再复用无重复校验3×3 宫的提取可以这样实现先把棋盘按 3 行一组分组ChunkM, 3每一组是 3 行再把组内 3 行按每 3 列切片并拼接得到该组对应的 3 个宫最终得到一个 9 宫数组每个宫是 9 个符号的一维元组。之后同样用HasDup逐个检查。这三个子校验各自产出布尔值最后用条件类型做与type ValidateT extends Reindeer[][] AllRowsUniqueT extends true ? AllColumnsUniqueT extends true ? AllRegionsUniqueT extends true ? true : false : false : false;从题目的 Vixen 提示看最终解析结果必须是字面量true/false而不能是boolean——这也是谓词predicate在类型层面的准确翻译Validate不是返回某个值而是让类型系统在两条不同分支上分别解析出唯一的真/假字面量。挑战的运行机制与工程细节理解这道题如何被验证能帮你判断自己实现的正确性。仓库根目录的 challenges/validate.ts 是挑战的校验脚本它做了两件事元数据校验遍历challenges/与challenges/aot/下所有挑战目录用 Ajv 依据metadata.schema.json校验metadata.json并检查目录名与id一致、prerequisites是合法 id 等。本题的 metadata.json 声明id为2024-22、难度为event、作者为TypeHero、无前置依赖。编译级测试读取每个挑战的tsconfig.json编译器选项将solutions/下的答案源码与tests.ts拼接成一个内存中的虚拟源文件createSourceFile生成配合自定义CompilerHost的getSourceFile拦截再用 TypeScript 编译器 APIcreateProgramgetPreEmitDiagnostics收集诊断无错误即输出绿色的✓ challenges/id/solutions/file。因此一个通过验证的实现必须满足两点测试用例中的ExpectEqual...全部成立即解析出的字面量类型精确匹配且整个拼接文件在编译期零诊断。本题的 tsconfig.json 开启了三项严格选项{ compilerOptions: { strict: true, exactOptionalPropertyTypes: true, noUncheckedIndexedAccess: true } }其中strict开启strictNullChecks等系列检查要求类型实现不能依赖隐式anynoUncheckedIndexedAccess意味着T[number]、M[J][I]这类索引访问在元素可能为undefined时不会静默通过这恰恰提醒我们在类型实现中要处理元组越界/缺省的情况。目前 solutions/1.ts 在本仓库中为空文件留待读者自行作答——你可以在本地运行仓库的校验脚本如pnpm validate或直接执行challenges/validate.ts来实时验证你的Validate实现是否通过全部 6 个断言。总结Reindeer Sudoku 是 Advent of TypeScript 系列中一道极具代表性的类型级算法题它把数独的三大约束行、列、宫完整翻译到 TypeScript 类型空间要求用元组拆分、递归条件类型、索引访问与字面量联合去重来实现一个严格的谓词类型。通过本题你可以系统掌握谓词类型predicate type在类型层面的含义解析为精确的true/false字面量用递归条件类型遍历任意深度的嵌套元组结构用去重后长度是否变化或逐元素累积比对判断元组无重复用映射类型实现矩阵转置与分组chunk等结构性变换理解 TypeHero 挑战仓库题目prompt— 骨架user— 断言tests— 编译校验validate四位一体的工程闭环以及 challenges/validate.ts 中基于 TypeScript Compiler API 的内存编译验证机制。如果你正在刷 Advent of TypeScript 或练习类型体操把这道题的三个子校验分别实现、再组合成一个Validate会比直接照抄任何答案更能建立对类型系统递归与映射能力的直觉。赞分享教育前端后端【免费下载链接】typeheroConnect, collaborate, and grow with a community of TypeScript developers项目地址https://gitcode.com/gh_mirrors/ty/typehero点击查看免费下载相关推荐用 TypeScript 类型系统实现 Connect 4TypeHero Advent of TypeScript 2024 第 23 天挑战全解用 TypeScript 类型系统实现 Connect 4TypeHero Advent of TypeScript 2024 第 23 天挑战全解 本篇技术教育前端后端TypeHero Advent of TypeScript 2024 第 24 天用 TypeScript 类型系统实现迷宫求解器 MoveTypeHero Advent of TypeScript 2024 第 24 天用 TypeScript 类型系统实现迷宫求解器 Move 导读 本文是 T教育前端后端用 TypeScript 类型系统实现井字棋TypeHero Advent of TypeScript 2023 第 21 天挑战深度解析用 TypeScript 类型系统实现井字棋TypeHero Advent of TypeScript 2023 第 21 天挑战深度解析 本文以 TypeH教育前端后端上一篇Windows热键冲突终极诊断指南Hotkey Detective完全解析下一篇思源宋体CN完全指南7种字重免费商用轻松提升你的中文排版品质创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考