关于 zod4
面向使用 Zod 4 的 TypeScript 开发者,提供版本迁移与惯用用法指南。内容涵盖破坏性变更、新功能和常见问题,帮助更新现有代码并编写符合新 API 的模式。
主要功能
- 01Zod 3 到 Zod 4 迁移指引
- 02破坏性变更与常见问题说明
- 03文件、模板字面量等新功能
- 04Zod Mini 与函数式 API 示例
- 05迁移清单与 codemod 说明
适用场景
- 01将项目从 Zod 3 升级到 Zod 4
- 02调整 record、对象和错误处理代码
- 03采用 Zod 4 新增的校验能力
- 04排查默认值和类型相关问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ kastalien-research/ thoughtbox-dot-claude --skill zod4安装后在 Claude Code 中输入/zod4确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/breaking-changes.mdmigration-checklist.mdnew-features.md详细介绍
Zod 4 专家指南
Zod 4 是一个重大版本,带来了显著的性能提升、更短的 TypeScript 编译时间,以及更简洁的 API。本指南介绍从 v3 迁移以及符合惯用方式的 Zod 4 用法。
快速迁移清单
深入了解之前,请先处理以下影响较大的破坏性变更:
| 变更 | Zod 3 | Zod 4 |
|---|---|---|
| Record 模式 | z.record(z.string()) | z.record(z.string(), z.string()) |
| 严格对象 | .strict() | z.strictObject({...}) |
| 透传 | .passthrough() | z.looseObject({...}) |
| 错误格式化 | err.format() | z.treeifyError(err) |
| 强制转换输入类型 | string | unknown |
安装 Zod 4:
npm install zod@^4.0.0
如需了解详细的破坏性变更,请参阅 ./reference/breaking-changes.md。
主要破坏性变更
1. z.record() 需要两个参数
// Zod 3 (BROKEN in v4)
z.record(z.string());
// Zod 4 (REQUIRED)
z.record(z.string(), z.string());
2. 严格/宽松对象语法
// Zod 3
z.object({ name: z.string() }).strict();
z.object({ name: z.string() }).passthrough();
// Zod 4
z.strictObject({ name: z.string() });
z.looseObject({ name: z.string() });
3. .default() 行为已更改
在 Zod 4 中,如果输入为 undefined,.default() 会直接返回默认值,而不进行解析。若要使用旧行为,请改用 .prefault():
// Zod 4: default must match OUTPUT type
const schema = z.string()
.transform(val => val.length)
.default(0); // Returns 0 directly, not parsed
// To parse the default (old behavior):
const schema = z.string()
.transform(val => val.length)
.prefault("tuna"); // "tuna" is parsed → 4
4. 错误处理变更
// Zod 3
const formatted = err.format();
const flat = err.flatten();
// Zod 4
const tree = z.treeifyError(err);
// Adding issues
err.issues.push({ /* new issue */ });
5. z.coerce 输入类型
const schema = z.coerce.string();
type Input = z.input<typeof schema>;
// Zod 3: string
// Zod 4: unknown
新功能
z.file() - 文件验证
const fileSchema = z.file()
.min(10_000) // minimum bytes
.max(1_000_000) // maximum bytes
.mime(["image/png", "image/jpeg"]);
z.templateLiteral() - 模板字面量类型
const css = z.templateLiteral([z.number(), z.enum(["px", "em", "rem"])]);
// `${number}px` | `${number}em` | `${number}rem`
const email = z.templateLiteral([
z.string().min(1),
"@",
z.string().max(64),
]);
.meta() - 模式元数据
z.string().meta({
id: "email_address",
title: "Email address",
description: "User's email",
examples: ["[email protected]"]
});
z.globalRegistry - 全局模式注册表
z.globalRegistry.add(mySchema, {
id: "user_schema",
title: "User",
description: "User data structure"
});
z.locales - 国际化
import { z } from "zod";
import { en } from "zod/locales/en";
z.config(z.locales.en()); // Configure error messages
z.strictObject() / z.looseObject()
// Rejects unknown keys
z.strictObject({ name: z.string() });
// Allows unknown keys (passthrough)
z.looseObject({ name: z.string() });
如需查看完整的新功能指南,请参阅 ./reference/new-features.md。
Zod Mini
Zod Mini(zod/mini)提供更小的打包体积,并采用可进行 tree-shaking 的函数式 API:
import * as z from "zod/mini";
// Functional checks instead of methods
const schema = z.pipe(
z.string(),
z.minLength(1),
z.maxLength(100),
z.regex(/^[a-z]+$/)
);
// Available functions
z.lt(value);
z.gt(value);
z.positive();
z.negative();
z.minLength(value);
z.maxLength(value);
z.regex(pattern);
z.trim();
z.toLowerCase();
z.toUpperCase();
迁移模式
模式 1:更新 z.record() 调用
搜索并替换:
// Find
z.record(valueSchema)
// Replace with
z.record(z.string(), valueSchema)
模式 2:更新严格对象
// Find
z.object({...}).strict()
// Replace with
z.strictObject({...})
模式 3:更新错误处理
// Find
try {
schema.parse(data);
} catch (err) {
if (err instanceof z.ZodError) {
const formatted = err.format();
}
}
// Replace with
try {
schema.parse(data);
} catch (err) {
if (err instanceof z.ZodError) {
const tree = z.treeifyError(err);
}
}
模式 4:修正默认值
如果在转换中使用 .default(),请检查默认值是否与输出类型匹配:
// If this breaks:
z.string().transform(s => s.length).default("hello")
// Change to:
z.string().transform(s => s.length).prefault("hello")
// OR
z.string().transform(s => s.length).default(5) // Match output type
如需查看完整的迁移清单,请参阅 ./reference/migration-checklist.md。
常见问题
| 错误 | 原因 | 修复方法 |
|---|---|---|
Expected 2 arguments, got 1 | z.record() 仅传入一个参数 | 添加键模式:z.record(z.string(), ...) |
Property 'strict' does not exist | .strict() 已移除 | 使用 z.strictObject() |
Property 'format' does not exist | .format() 已移除 | 使用 z.treeifyError(err) |
.default() 类型不匹配 | 默认值必须与输出类型匹配 | 使用 .prefault() 或修正默认值类型 |
Codemod
有一个由社区维护的 codemod 可供使用:
npx zod-v3-to-v4
它可以自动处理许多破坏性变更修复。
资源
评论
支持 Markdown