Zod Codecs完全教程:用两行代码实现数据的双向编码解码(encode/decode)
【免费下载链接】zodTypeScript-first schema validation with static type inference项目地址: https://gitcode.com/GitHub_Trending/zo/zod
Zod是 TypeScript 生态中最流行的 schema 校验库,而Zod Codecs(自zod@4.1引入)是它最实用的新特性之一:用一行z.codec()就能定义数据的双向转换,decode把外部数据"解码"成你喜欢的类型,encode再"编码"回去,轻松搞定网络请求里 JSON 字符串与 JavaScript 对象之间的来回转换。
为什么需要 Zod Codecs?
做前后端开发时你一定遇到过这种尴尬:
- 服务器发来的是 ISO 时间字符串
"2024-01-15T10:30:00.000Z",代码里却想直接用Date对象 - 表单提交来的数字是字符串
"42.5",业务逻辑需要的是number - 发请求前又得把它们老老实实转回字符串
传统做法是两头各写一堆new Date(...)和.toISOString()转换代码,枯燥且容易漏。Zod Codecs 的解决方案是:把"校验"和"双向转换"合并进同一个 schema,客户端和服务器共享一份定义,decode/encode各管一个方向。
两行核心代码:z.codec() 基础用法
创建一个 Codec 只需三步:输入 schema、输出 schema、转换函数。以"ISO 字符串 ↔ Date 对象"为例:
const stringToDate = z.codec( z.iso.datetime(), // 输入 schema:ISO 日期字符串 z.date(), // 输出 schema:Date 对象 { decode: (isoString) => new Date(isoString), // 解码:字符串 → Date encode: (date) => date.toISOString(), // 编码:Date → 字符串 } );使用极其清爽:
stringToDate.decode("2024-01-15T10:30:00.000Z"); // => Date 对象 stringToDate.encode(new Date("2024-01-15T10:30:00.000Z")); // => 字符串💡 实现细节:
z.codec()本质上是 packages/zod/src/v4/classic/schemas.ts 中的codec函数,内部把decode/encode分别挂成管道(pipe)的正向与反向转换函数。
parse 与 decode 的区别:类型签名不同
.parse()和.decode()在运行时行为完全相同,但类型检查强度不同:
parse()接受unknown输入 —— 传错类型编译器不报错,运行时才失败decode()/encode()输入强类型—— 传个数字进去,TypeScript 直接标红
stringToDate.parse(12345); // ✅ 编译通过(运行时才炸) stringToDate.decode(12345); // ❌ 编译报错:number 不能赋给 string正因为 encode/decode 隐含"转换"语义,输入通常已是强类型,Zod 选择把错误提前暴露到编译期。
进阶技巧:让 Codec 融入复杂结构
1. 可组合性:嵌套到对象和数组里
Codec 就是普通 schema,想放哪放哪:
const payloadSchema = z.object({ startDate: stringToDate }); payloadSchema.decode({ startDate: "2024-01-15T10:30:00.000Z" }); // => { startDate: Date }一个对象 schema 就能让整包数据自动完成双向转换,这是网络边界场景(API 请求/响应)最大的价值点。
2. z.invertCodec():一键反转方向
有了stringToDate,想要反方向的dateToString?不用重写:
const dateToString = z.invertCodec(stringToDate);⚠️ 注意:它只反转你传入的那一层 codec,不会递归反转嵌套在其他 schema 里的 codec,嵌套层需要在使用处分别反转。
3. 异步与安全变体
和.transform()一样支持异步转换函数,也有一整套"安全"API:
stringToDate.decodeAsync("2024-01-15T10:30:00.000Z"); // => Promise<Date> stringToDate.safeDecode("2024-01-15T10:30:00.000Z"); // => { success: true, data: Date } | { success: false, error: ZodError }4. 内置的 stringbool:现成的双向转换器
z.stringbool()早于 Codecs 存在,如今内部已用 codec 重新实现,可把"true"/"false"/"yes"/"no"与布尔值互相转换:
const sb = z.stringbool({ truthy: ["yes", "y"], falsy: ["no", "n"] }); sb.decode("yes"); // => true sb.encode(false); // => "no"(取数组第一个元素)避坑指南:encode 方向的规则细节
这是新手最容易踩坑的部分,规则可以总结为:
| 特性 | decode(正向) | encode(反向) |
|---|---|---|
.refine()/.min()等校验 | ✅ 执行 | ✅ 执行(两遍校验) |
.default()/.prefault() | ✅ 应用 | ❌ 不应用 |
.catch() | ✅ 应用 | ❌ 不应用 |
.transform() | ✅ 执行 | ❌直接抛运行时错误 |
几个关键细节:
- default 只在正向生效。
z.string().default("hello")对decode(undefined)返回"hello",但encode(undefined)会报错——因为加了默认值后输入类型才变成| undefined,而 encode 的入参是强类型的输出侧。 - transform 是单向的。schema 里任何
.transform()都会让encode()抛出运行时错误(不是 ZodError),看到Encountered unidirectional transform during encode就该去查是谁加了 transform。 - refine 是双向的。比如
stringToDate.refine(date => date.getFullYear() >= 2000),encode 一个 1999 年的日期同样会触发校验失败。
常用 Codec 配方:直接抄作业
官方文档整理了一批经过测试的现成实现,建议你复制到自己的项目里按需修改(完整清单见 packages/docs/content/codecs.mdx):
- stringToNumber/stringToInt:字符串转数字,如
decode("42.5") => 42.5 - epochSecondsToDate:Unix 时间戳(秒)与
Date互转 - json(schema):把 JSON 字符串解析成结构化数据并反序列化回去,出错时通过
ctx.issues抛出带路径的invalid_format错误 - base64ToBytes/hexToBytes:base64、十六进制字符串与
Uint8Array互转 - stringToURL:URL 字符串与
URL对象互转 - uriComponent:基于
encodeURIComponent/decodeURIComponent的组件编码
一个最典型的 JSON codec:
const jsonCodec = (schema: any) => z.codec(z.string(), schema, { decode: (jsonString, ctx) => { try { return JSON.parse(jsonString); } catch (err: any) { ctx.issues.push({ code: "invalid_format", format: "json", message: err.message }); return z.NEVER; } }, encode: (value) => JSON.stringify(value), });总结
| 需求 | 用这个 |
|---|---|
| 数据进来时转换 + 校验 | decode()(等价于parse()) |
| 数据出去时序列化 | encode() |
| 反向 codec | z.invertCodec() |
| 不想抛异常 | safeDecode()/safeEncode() |
| 字符串布尔值 | z.stringbool() |
Zod Codecs 的核心理念:一份 schema,双向转换,客户端和服务器共用。掌握z.codec()的两行基本语法 + encode 方向的规则细节,就能覆盖 90% 的场景。更多 API 细节可查阅官方文档 packages/docs/content/codecs.mdx,核心实现位于 packages/zod/src/v4/core/schemas.ts。
【免费下载链接】zodTypeScript-first schema validation with static type inference项目地址: https://gitcode.com/GitHub_Trending/zo/zod
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考