freeCodeCamp 每日编程挑战 297:用 JavaScript 手写 Schema 校验器(联合类型篇)
freeCodeCamp 每日编程挑战 297用 JavaScript 手写 Schema 校验器联合类型篇【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇技术指南聚焦 freeCodeCamp 开源仓库中「每日编程挑战」系列的Challenge 297: Schema Validator Part 3挑战原文。该挑战要求读者仅凭 JavaScript 基础语法实现一个微型 Schema 校验函数核心难点在于理解**联合类型Union Type**的语义与typeof类型守卫的组合运用。读完本文你将掌握如何用原生 JS 完成字段类型校验 枚举值白名单校验的组合判断并了解该挑战在 6 个递进式 Schema Validator 系列中的定位、全部 11 条测试用例的判定依据以及它背后的课程结构组织方式。挑战概览判断对象是否符合给定 SchemaChallenge 297 是「Schema Validator」系列Challenge 295–300的第三关延续了前两关给定一个对象JS或字典Python判断其是否匹配指定 Schema的核心任务。本关在 Challenge 296 的username: string、posts: number、verified: boolean三个基础字段之上新增了第四个字段role并首次引入联合类型语法Roles user | creator | moderator | staff | admin { username: string, posts: number, verified: boolean, role: Roles }规则有两条竖线|符号表示或role的值必须是列出的Roles取值之一即user、creator、moderator、staff、admin五个字符串之一允许额外的键Extra keys are allowed即对象中即使存在 schema 未声明的字段如followers也不会导致校验失败。字段语义与校验规则拆解必选字段的类型约束字段期望类型校验手段usernamestringtypeof obj.username stringpostsnumbertypeof obj.posts numberverifiedbooleantypeof obj.verified booleanrole联合类型Rolesroles.includes(obj.role)需要注意的细节posts只要求是number类型没有范围限制0也是合法值测试用例中多次出现posts: 0返回true即为佐证四个字段均为必填任何字段缺失都会导致校验失败——这正是本关与后面 Challenge 298 引入可选字段supporter?之间的区别username允许为空字符串只要类型是string即可Challenge 295 中已有明确用例额外键如followers: 70不影响判定结果。联合类型的落地实现由于本关要求仅用原生 JavaScript、不引入第三方校验库联合类型Roles需要借助数组 includes方法来模拟枚举判定const roles [user, creator, moderator, staff, admin];这是手工实现 Schema 校验中最常用也最直观的白名单技巧。值得指出的是roles.includes(obj.role)这一写法本身既校验了值是否在枚举内也隐含排除了role为数字、布尔值等非法类型的情况例如role: true、role: guest、role: friend都会因为不在白名单中而返回false。完整参考实现官方 --solutions--该挑战在 frontmatter 的--solutions--区块中给出了官方参考解function isValidSchema(obj) { const roles [user, creator, moderator, staff, admin]; return ( typeof obj.username string typeof obj.posts number typeof obj.verified boolean roles.includes(obj.role) ); }实现思路拆解用typeof依次对三个基础字段做类型守卫type guard任何一项不满足都会因短路而直接返回falseroles.includes(obj.role)充当联合类型校验器五个合法取值全部命中函数不遍历、不拒绝多余键天然满足Extra keys are allowed规则——这正是手工实现与严格校验库如 JSON Schema 的additionalProperties: false的核心差异。逐条解析11 个测试用例的判定依据挑战 frontmatter 的--hints--区块给出了 11 条断言基于 Chai 的assert.isTrue/assert.isFalse可以按正向通过与反向拒绝两组来理解返回true的 5 个用例输入对象通过原因{ username: henry, posts: 0, verified: true, role: staff }四个字段类型全对posts: 0合法{ username: sara, posts: 45, verified: false, role: creator, followers: 70 }含额外键followers允许{ username: penelope, posts: 20, verified: true, role: admin }标准合法对象{ username: kevin, posts: 0, verified: false, role: user }标准合法对象{ username: george, posts: 15, verified: true, role: moderator }标准合法对象返回false的 6 个用例输入对象拒绝原因{ username: david, posts: 0, verified: false, role: guest }role不在Roles白名单中联合类型校验失败{ username: wendy, posts: 10, verified: true }role字段缺失必填字段缺失{ username: fabian, posts: 1, verified: true, role: true }role类型错误布尔值不在枚举内{ username: 8, posts: 1, verified: true, role: user }username类型错误应为 string{ username: penny, posts: 10, verified: true, role: staff }posts类型错误字符串 10 不是 number{ username: john, posts: 1, verified: true, role: admin }posts与verified类型均错误从反向用例可以看出本关刻意覆盖了五类典型错误枚举值越界guest、必填字段缺失、字段类型错误数字/布尔/字符串混用。这也呼应了typeof的局限——typeof 10是string与number严格不等所以posts: 10必然被拒。起点代码与完成标准挑战的--seed--区块给出了初始代码框架function isValidSchema(obj) { return obj; }参赛者需要补全函数体。注意这里的陷阱占位实现return obj返回的是对象本身truthy一旦测试框架对返回值做布尔判断任何输入都会通过只有真正补全校验逻辑11 条断言才会全部通过。这体现了 freeCodeCamp 挑战一贯的先给最小占位、再驱动你写出完整实现的设计哲学。从源码理解该挑战在仓库中的位置课程结构Schema Validator 六部曲通过查看 daily-coding-challenges-javascript 模块定义 中的challengeOrder可以看到本关id6a0dcc730cb92a616f86f0c1处于整组 365 道 JavaScript 每日挑战的末尾序列中与前后挑战构成渐进式教学曲线Challenge 295Part 1单字段username: string学习typeof基础Challenge 296Part 2三字段username/posts/verified学习多条件组合Challenge 297Part 3本关新增联合类型role: Roles学习白名单枚举校验Challenge 298Part 4新增可选字段supporter?学习undefined判空Challenge 299Part 5新增数组字段badges: string[]学习Array.isArray与everyChallenge 300Part 6升级为嵌套结构users: UserProfile[]学习递归校验模式。每一关都在上一关答案上叠加一个新语言特性最终在 Part 6 中形成类型守卫 枚举 可选字段 数组 嵌套对象的完整手工校验器。这种递进式难度设计也是本模块blockLayout: legacy-challenge-list、challengeType: 28每日编程挑战类型所承载的教学目标。后端支撑Daily Coding Challenge API该系列挑战的题目数据由 API 侧的每日挑战模块提供。在 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 中定义了GET /daily-coding-challenge/date/:date、/day/:day、/today、/month/:month、/all、/newest等公开端点按美国中部时区US Central的日期从dailyCodingChallenges表中查询当日题目且不会返回晚于当前日期的挑战源码注释明确写着挑战数据截止于 2026-08-10。模块说明见 api/src/daily-coding-challenge/README.md。前端呈现每日挑战页面用户实际解题的界面由 client/src/client-only-routes/show-daily-coding-challenge.tsx 渲染题目文件本身则存放在curriculum/challenges/english/blocks/daily-coding-challenges-javascript/目录下与daily-coding-challenges-python模块构成跨语言JS/Python的同一套题目集。举一反三从本关延伸的工程启示手写校验 vs 校验库本关用 4 行条件表达式实现校验适合体量小、字段固定的场景当 schema 变复杂可选、嵌套、数组时真实项目中往往会选择 JSON Schema / zod / TypeBox 等方案。有趣的是仓库 API 层恰恰使用了fastify/type-provider-typebox做请求参数校验见 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 顶部的 schema 引入可以对照学习手写校验与声明式校验两种路径的差异。typeof的已知陷阱typeof null object、typeof [] object等历史行为意味着本关的typeof方案可以严格区分string/number/boolean但面对null、数组、嵌套对象时必须改用 null、Array.isArray等更精确的手段——这正是 Part 5 引入Array.isArray(obj.badges)的原因。测试驱动的完成标准11 条assert断言既是验收标准也是题面规格说明specification by example。解题时逐条对照反向用例可以快速定位自己实现的漏洞例如忘记处理缺失role或多键允许这两种边界。小结Challenge 297 用一道小而精的题目教会了手工 Schema 校验中两个最核心的能力用typeof做类型守卫、用数组includes模拟联合类型枚举。配合官方提供的参考实现与 11 条断言用例读者可以完整验证自己的解法。如果想要继续深入建议按顺序完成同系列的 Challenge 298–300逐步补上可选字段、数组字段与嵌套对象这三块拼图最终具备不依赖任何第三方库、徒手写出中等复杂度校验器的能力。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →