十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Zod 数据验证实践:从订单字段到接口解析,三个场景完成上手

Zod 数据验证实践:从订单字段到接口解析,三个场景完成上手 Zod 数据验证实践从订单字段到接口解析三个场景完成上手【免费下载链接】zodTypeScript-first schema validation with static type inference项目地址: https://gitcode.com/GitHub_Trending/zo/zod周五晚上的一次线上告警聊天消息的回复关系偶发丢失。排查后发现后端悄悄把replyTo字段从字符串换成了数字前端一直按字符串处理问题暴露时脏数据已经流了半天。这类接口契约与前端假设不一致的坑正是 TypeScript 数据验证最典型的用武之地在数据进入业务的边界处先用 Zod 按 schema 校验一遍不合规则直接拦下而不是让坏值一路渗透到深处。为什么 Zod 值得进项目一句话schema 只写一份类型由z.infer从 schema 推断出来——校验规则和类型同源不用人工保持同步运行时零依赖打包体积基本可以忽略。三十秒装好先分清两种过一遍这一节解决什么问题数据进来之后校验失败时到底该抛错还是该返回结果先装npm install zodimport { z } from zod; const schema z.object({ port: z.number().int() }); // 失败直接抛 ZodError适合必须对的内部环节 const ok schema.parse({ port: 8080 }); // 失败返回结果对象方便取错误信息做展示 const res schema.safeParse({ port: 8080 }); if (!res.success) { console.log(res.error.issues[0].message); }区分口径很朴素自己构造的数据用parse来源不受控的数据用safeParse把异常收敛在边界处。官方文档里用这张图描述数据流向未知输入穿过parse变成带类型的输出图中decode/encode双向流是 v4 的 codec 模型入门阶段知道有这条路径即可。场景一电商订单的嵌套结构与默认值这一节解决什么问题上游网关推来的订单结构有嵌套、有可缺项业务代码不能每处都手写?? []。const orderSchema z.object({ orderNo: z.string().min(1), amount: z.number().nonnegative(), // 金额不允许为负 items: z.array(z.object({ sku: z.string(), quantity: z.number().int().min(1), })).min(1), shipTo: z.object({ name: z.string(), phone: z.string(), city: z.string().optional(), // 允许缺传了必须是字符串 }), notes: z.string().optional(), tags: z.array(z.string()).default([]), // 缺省时兜底空数组 }); type Order z.infertypeof orderSchema; // 用 schema 锁类型为什么这么写optional只表示字段可以不出现传进来之后仍是原始类型default则由 Zod 主动补值下游可以默认字段必在。把这两种语义在 schema 里分开表达比在业务代码里到处补兜底更稳。场景二聊天消息的跨字段校验这一节解决什么问题单字段规则都过了但回复类消息却没有指向原消息这种跨字段矛盾schema 得会自己抓出来。const messageSchema z.object({ id: z.string(), type: z.enum([text, reply, system]), content: z.string().max(2000), createdAt: z.number(), // 毫秒时间戳 replyTo: z.string().optional(), // 原消息 id }).refine( (m) m.type ! reply || Boolean(m.replyTo), { message: reply 类型消息必须指定原消息, path: [replyTo] } );注意这里能写在字段上的规则就写在字段上refine只留给需要看一眼别的字段的场景path决定错误挂在哪个字段下前端定位问题时更直观。场景三配置解析与强制转换这一节解决什么问题.env或配置接口里一切值都是字符串8080不该在业务里再被Number()一遍。const configSchema z.object({ PORT: z.coerce.number().int().min(1).max(65535), // 字符串强转为数字 LOG_LEVEL: z.enum([info, warn, error]).default(info), EXPIRES: z.coerce.date().optional(), // 日期字符串转 Date }); const cfg configSchema.parse({ PORT: 8080, EXPIRES: 2026-12-31 }); console.log(typeof cfg.PORT, cfg.EXPIRES instanceof Date);coerce的定位是值本身没问题只是类型不对——配置解析、表单输入正是这种场景的日常转换和校验在同一步完成。新手避坑清单这一节解决什么问题前三个场景都跑通之后下面几处仍是最容易翻车的地方。parse / safeParse 混用在错误处理路径上用parse抛错又在上层catch后吞掉错误信息就丢了。来源不受控的数据一律safeParse。忘了z.infer锁类型schema 改了一行手写的类型定义没跟上两边悄悄分叉。类型永远从 schema 推。把 optional 当 nullableoptional只表示字段可缺接口若可能显式传null需要.nullable()或.nullish()别指望optional替你接住null。z.coerce.boolean()的陷阱v4 按真值判断false会解析成true只有空串、0、undefined得false。配置开关建议写z.enum([true, false])再自己转。下一步可以做什么这一节给三条最短的继续路径把场景二里的type字段改用z.discriminatedUnion重写体会按判别字段分流各子类型翻一翻 v4 classic 测试目录每种写法的官方样例都在里面需要与外部工具对接时查看 schema 的 JSON Schema 转换能力若维护 v3 风格代码可对照 v3 中文文档【免费下载链接】zodTypeScript-first schema validation with static type inference项目地址: https://gitcode.com/GitHub_Trending/zo/zod创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表