zod
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseZod: TypeScript-First Schema Validation
Zod:以TypeScript优先的Schema验证库
Overview
概述
Zod is a TypeScript-first validation library that enables developers to define schemas for validating data at runtime while automatically inferring static TypeScript types. With zero dependencies and a 2kb core bundle (gzipped), Zod provides immutable, composable validation with comprehensive error handling.
Zod是一个以TypeScript优先的验证库,允许开发者定义Schema以在运行时验证数据,同时自动推断静态TypeScript类型。Zod零依赖,核心包压缩后仅2kb,提供不可变、可组合的验证能力以及全面的错误处理机制。
Installation
安装
bash
bun add zodbash
bun add zodor
or
bun add zod
bun add zod
or
or
bun add zod
bun add zod
or
or
yarn add zod
**Requirements**:
- TypeScript v5.5+ with `"strict": true` in `tsconfig.json`
- Zod 4.x (4.1.12+)
**Important**: This skill documents **Zod 4.x** features. The following APIs require Zod 4 and are NOT available in Zod 3.x:
- `z.codec()` - Bidirectional transformations
- `z.iso.date()`, `z.iso.time()`, `z.iso.datetime()`, `z.iso.duration()` - ISO format validators
- `z.toJSONSchema()` - JSON Schema generation
- `z.treeifyError()`, `z.prettifyError()`, `z.flattenError()` - New error formatting helpers
- `.meta()` - Enhanced metadata (Zod 3.x only has `.describe()`)
- Unified `error` parameter - Replaces `message`, `invalid_type_error`, `required_error`, `errorMap`
For Zod 3.x compatibility or migration guidance, see https://zod.devyarn add zod
**要求**:
- TypeScript v5.5+,且`tsconfig.json`中`"strict": true`已启用
- Zod 4.x(4.1.12+)
**重要提示**:本技能文档针对**Zod 4.x**特性。以下API仅支持Zod 4,在Zod 3.x中不可用:
- `z.codec()` - 双向转换
- `z.iso.date()`、`z.iso.time()`、`z.iso.datetime()`、`z.iso.duration()` - ISO格式验证器
- `z.toJSONSchema()` - JSON Schema生成
- `z.treeifyError()`、`z.prettifyError()`、`z.flattenError()` - 新的错误格式化工具
- `.meta()` - 增强型元数据(Zod 3.x仅支持`.describe()`)
- 统一的`error`参数 - 替代`message`、`invalid_type_error`、`required_error`、`errorMap`
如需Zod 3.x兼容性或迁移指南,请访问https://zod.devMigrating from Zod v3 to v4
从Zod v3迁移到v4
Load for complete v3 to v4 migration documentation.
references/migration-guide.md加载以获取完整的v3到v4迁移文档。
references/migration-guide.mdQuick Summary
快速摘要
Zod v4 introduces breaking changes for better performance:
- Error customization: Use unified parameter (replaces
error,message,invalid_type_error)required_error - Number validation: Stricter - rejects and unsafe integers
Infinity - String formats: Now top-level functions (vs
z.email())z.string().email() - Object defaults: Applied even in optional fields
- Deprecated APIs: Use (not
.extend()),.merge()(notz.treeifyError())error.format() - Function validation: Use method
.implement() - UUID validation: Stricter RFC 9562/4122 compliance
→ Load for: Complete breaking changes, migration checklist, gradual migration strategy, rollback instructions
references/migration-guide.mdZod v4引入了一些破坏性变更以提升性能:
- 错误自定义:使用统一的参数(替代
error、message、invalid_type_error)required_error - 数字验证:更严格 - 拒绝和不安全整数
Infinity - 字符串格式:现为顶级函数(替代
z.email())z.string().email() - 对象默认值:即使是可选字段也会应用默认值
- 已弃用API:使用(而非
.extend())、.merge()(而非z.treeifyError())error.format() - 函数验证:使用方法
.implement() - UUID验证:更严格遵循RFC 9562/4122标准
→ 加载查看: 完整的破坏性变更、迁移清单、渐进式迁移策略、回滚说明
references/migration-guide.mdCore Concepts
核心概念
Basic Usage Pattern
基础使用模式
typescript
import { z } from "zod";
// Define schema
const UserSchema = z.object({
username: z.string(),
age: z.number().int().positive(),
email: z.string().email(),
});
// Infer TypeScript type
type User = z.infer<typeof UserSchema>;
// Validate data (throws on error)
const user = UserSchema.parse(data);
// Validate data (returns result object)
const result = UserSchema.safeParse(data);
if (result.success) {
console.log(result.data); // Typed!
} else {
console.error(result.error); // ZodError
}typescript
import { z } from "zod";
// 定义Schema
const UserSchema = z.object({
username: z.string(),
age: z.number().int().positive(),
email: z.string().email(),
});
// 推断TypeScript类型
type User = z.infer<typeof UserSchema>;
// 验证数据(验证失败时抛出错误)
const user = UserSchema.parse(data);
// 验证数据(返回结果对象)
const result = UserSchema.safeParse(data);
if (result.success) {
console.log(result.data); // 具备类型提示!
} else {
console.error(result.error); // ZodError
}Parsing Methods
解析方法
Use the appropriate parsing method based on error handling needs:
- - Throws
.parse(data)on invalid input; returns strongly-typed data on successZodError - - Returns
.safeParse(data)or{ success: true, data }(no exceptions){ success: false, error } - - For schemas with async refinements/transforms
.parseAsync(data) - - Async version that doesn't throw
.safeParseAsync(data)
Best Practice: Use to avoid try-catch blocks and leverage discriminated unions.
.safeParse()根据错误处理需求选择合适的解析方法:
- - 输入无效时抛出
.parse(data);成功时返回强类型数据ZodError - - 返回
.safeParse(data)或{ success: true, data }(不抛出异常){ success: false, error } - - 适用于包含异步细化/转换的Schema
.parseAsync(data) - - 异步版本,不会抛出异常
.safeParseAsync(data)
最佳实践:使用避免try-catch代码块,利用区分联合类型的优势。
.safeParse()Primitive Types
原始类型
Strings
字符串
typescript
z.string() // Basic string
z.string().min(5) // Minimum length
z.string().max(100) // Maximum length
z.string().length(10) // Exact length
z.string().email() // Email validation
z.string().url() // URL validation
z.string().uuid() // UUID format
z.string().regex(/^\d+$/) // Custom pattern
z.string().startsWith("pre") // Prefix check
z.string().endsWith("suf") // Suffix check
z.string().trim() // Auto-trim whitespace
z.string().toLowerCase() // Auto-lowercase
z.string().toUpperCase() // Auto-uppercase
// ISO formats (Zod 4+)
z.iso.date() // YYYY-MM-DD
z.iso.time() // HH:MM:SS
z.iso.datetime() // ISO 8601 datetime
z.iso.duration() // ISO 8601 duration
// Network formats
z.ipv4() // IPv4 address
z.ipv6() // IPv6 address
z.cidrv4() // IPv4 CIDR notation
z.cidrv6() // IPv6 CIDR notation
// Other formats
z.jwt() // JWT token
z.nanoid() // Nanoid
z.cuid() // CUID
z.cuid2() // CUID2
z.ulid() // ULID
z.base64() // Base64 encoded
z.hex() // Hexadecimaltypescript
z.string() // 基础字符串类型
z.string().min(5) // 最小长度
z.string().max(100) // 最大长度
z.string().length(10) // 精确长度
z.string().email() // 邮箱验证
z.string().url() // URL验证
z.string().uuid() // UUID格式
z.string().regex(/^\d+$/) // 自定义正则匹配
z.string().startsWith("pre") // 前缀检查
z.string().endsWith("suf") // 后缀检查
z.string().trim() // 自动去除首尾空格
z.string().toLowerCase() // 自动转换为小写
z.string().toUpperCase() // 自动转换为大写
// ISO格式(Zod 4+)
z.iso.date() // YYYY-MM-DD格式
z.iso.time() // HH:MM:SS格式
z.iso.datetime() // ISO 8601日期时间格式
z.iso.duration() // ISO 8601时长格式
// 网络格式
z.ipv4() // IPv4地址
z.ipv6() // IPv6地址
z.cidrv4() // IPv4 CIDR表示法
z.cidrv6() // IPv6 CIDR表示法
// 其他格式
z.jwt() // JWT令牌
z.nanoid() // Nanoid
z.cuid() // CUID
z.cuid2() // CUID2
z.ulid() // ULID
z.base64() // Base64编码
z.hex() // 十六进制Numbers
数字
typescript
z.number() // Basic number
z.number().int() // Integer only
z.number().positive() // > 0
z.number().nonnegative() // >= 0
z.number().negative() // < 0
z.number().nonpositive() // <= 0
z.number().min(0) // Minimum value
z.number().max(100) // Maximum value
z.number().gt(0) // Greater than
z.number().gte(0) // Greater than or equal
z.number().lt(100) // Less than
z.number().lte(100) // Less than or equal
z.number().multipleOf(5) // Must be multiple of 5
z.int() // Shorthand for z.number().int()
z.int32() // 32-bit integer
z.nan() // NaN valuetypescript
z.number() // 基础数字类型
z.number().int() // 仅允许整数
z.number().positive() // > 0
z.number().nonnegative() // >= 0
z.number().negative() // < 0
z.number().nonpositive() // <= 0
z.number().min(0) // 最小值
z.number().max(100) // 最大值
z.number().gt(0) // 大于
z.number().gte(0) // 大于等于
z.number().lt(100) // 小于
z.number().lte(100) // 小于等于
z.number().multipleOf(5) // 必须是5的倍数
z.int() // z.number().int()的简写
z.int32() // 32位整数
z.nan() // NaN值Coercion (Type Conversion)
类型转换
typescript
z.coerce.string() // Convert to string
z.coerce.number() // Convert to number
z.coerce.boolean() // Convert to boolean
z.coerce.bigint() // Convert to bigint
z.coerce.date() // Convert to Date
// Example: Parse query parameters
const QuerySchema = z.object({
page: z.coerce.number().int().positive(),
limit: z.coerce.number().int().max(100).default(10),
});
// "?page=5&limit=20" -> { page: 5, limit: 20 }typescript
z.coerce.string() // 转换为字符串
z.coerce.number() // 转换为数字
z.coerce.boolean() // 转换为布尔值
z.coerce.bigint() // 转换为BigInt
z.coerce.date() // 转换为Date对象
// 示例:解析查询参数
const QuerySchema = z.object({
page: z.coerce.number().int().positive(),
limit: z.coerce.number().int().max(100).default(10),
});
// "?page=5&limit=20" → { page: 5, limit: 20 }Other Primitives
其他原始类型
typescript
z.boolean() // Boolean
z.date() // Date object
z.date().min(new Date("2020-01-01"))
z.date().max(new Date("2030-12-31"))
z.bigint() // BigInt
z.symbol() // Symbol
z.null() // Null
z.undefined() // Undefined
z.void() // Void (undefined)typescript
z.boolean() // 布尔类型
z.date() // Date对象
z.date().min(new Date("2020-01-01"))
z.date().max(new Date("2030-12-31"))
z.bigint() // BigInt
z.symbol() // Symbol
z.null() // Null
z.undefined() // Undefined
z.void() // Void(即undefined)Complex Types
复杂类型
Objects
对象
typescript
const PersonSchema = z.object({
name: z.string(),
age: z.number(),
address: z.object({
street: z.string(),
city: z.string(),
country: z.string(),
}),
});
type Person = z.infer<typeof PersonSchema>;
// Object methods
PersonSchema.shape // Access shape
PersonSchema.keyof() // Get union of keys
PersonSchema.extend({ role: z.string() }) // Add fields
PersonSchema.pick({ name: true }) // Pick specific fields
PersonSchema.omit({ age: true }) // Omit fields
PersonSchema.partial() // Make all fields optional
PersonSchema.required() // Make all fields required
PersonSchema.deepPartial() // Recursively optional
// Strict vs loose objects
z.strictObject({ ... }) // No extra keys allowed (throws)
z.object({ ... }) // Strips extra keys (default)
z.looseObject({ ... }) // Allows extra keystypescript
const PersonSchema = z.object({
name: z.string(),
age: z.number(),
address: z.object({
street: z.string(),
city: z.string(),
country: z.string(),
}),
});
type Person = z.infer<typeof PersonSchema>;
// 对象方法
PersonSchema.shape // 访问对象结构
PersonSchema.keyof() // 获取键名的联合类型
PersonSchema.extend({ role: z.string() }) // 添加字段
PersonSchema.pick({ name: true }) // 挑选指定字段
PersonSchema.omit({ age: true }) // 排除指定字段
PersonSchema.partial() // 将所有字段设为可选
PersonSchema.required() // 将所有字段设为必填
PersonSchema.deepPartial() // 递归将所有字段设为可选
// 严格模式与宽松模式对象
z.strictObject({ ... }) // 不允许额外键(存在则抛出错误)
z.object({ ... }) // 自动移除额外键(默认行为)
z.looseObject({ ... }) // 允许额外键Arrays
数组
typescript
z.array(z.string()) // String array
z.array(z.number()).min(1) // At least 1 element
z.array(z.number()).max(10) // At most 10 elements
z.array(z.number()).length(5) // Exactly 5 elements
z.array(z.number()).nonempty() // At least 1 element
// Nested arrays
z.array(z.array(z.number())) // number[][]typescript
z.array(z.string()) // 字符串数组
z.array(z.number()).min(1) // 至少包含1个元素
z.array(z.number()).max(10) // 最多包含10个元素
z.array(z.number()).length(5) // 精确包含5个元素
z.array(z.number()).nonempty() // 至少包含1个元素
// 嵌套数组
z.array(z.array(z.number())) // number[][]Tuples
元组
typescript
z.tuple([z.string(), z.number()]) // [string, number]
z.tuple([z.string(), z.number()]).rest(z.boolean()) // [string, number, ...boolean[]]typescript
z.tuple([z.string(), z.number()]) // [string, number]
z.tuple([z.string(), z.number()]).rest(z.boolean()) // [string, number, ...boolean[]]Enums and Literals
枚举与字面量
typescript
// Enum
const RoleEnum = z.enum(["admin", "user", "guest"]);
type Role = z.infer<typeof RoleEnum>; // "admin" | "user" | "guest"
// Literal values
z.literal("exact_value")
z.literal(42)
z.literal(true)
// Native TypeScript enum
enum Fruits {
Apple,
Banana,
}
z.nativeEnum(Fruits)
// Enum methods
RoleEnum.enum.admin // "admin"
RoleEnum.exclude(["guest"]) // Exclude values
RoleEnum.extract(["admin", "user"]) // Include onlytypescript
// 枚举
const RoleEnum = z.enum(["admin", "user", "guest"]);
type Role = z.infer<typeof RoleEnum>; // "admin" | "user" | "guest"
// 字面量值
z.literal("exact_value")
z.literal(42)
z.literal(true)
// 原生TypeScript枚举
enum Fruits {
Apple,
Banana,
}
z.nativeEnum(Fruits)
// 枚举方法
RoleEnum.enum.admin // "admin"
RoleEnum.exclude(["guest"]) // 排除指定值
RoleEnum.extract(["admin", "user"]) // 仅保留指定值Unions
联合类型
typescript
// Basic union
z.union([z.string(), z.number()])
// Discriminated union (better performance & type inference)
const ResponseSchema = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.any() }),
z.object({ status: z.literal("error"), message: z.string() }),
]);
type Response = z.infer<typeof ResponseSchema>;
// { status: "success", data: any } | { status: "error", message: string }typescript
// 基础联合类型
z.union([z.string(), z.number()])
// 可区分联合类型(性能更优、类型推断更好)
const ResponseSchema = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.any() }),
z.object({ status: z.literal("error"), message: z.string() }),
]);
type Response = z.infer<typeof ResponseSchema>;
// { status: "success", data: any } | { status: "error", message: string }Intersections
交叉类型
typescript
const BaseSchema = z.object({ id: z.string() });
const ExtendedSchema = z.object({ name: z.string() });
const Combined = z.intersection(BaseSchema, ExtendedSchema);
// Equivalent to: z.object({ id: z.string(), name: z.string() })typescript
const BaseSchema = z.object({ id: z.string() });
const ExtendedSchema = z.object({ name: z.string() });
const Combined = z.intersection(BaseSchema, ExtendedSchema);
// 等价于:z.object({ id: z.string(), name: z.string() })Records and Maps
记录与映射
typescript
// Record: object with typed keys and values
z.record(z.string()) // { [key: string]: string }
z.record(z.string(), z.number()) // { [key: string]: number }
// Partial record (some keys optional)
z.partialRecord(z.enum(["a", "b"]), z.string())
// Map
z.map(z.string(), z.number()) // Map<string, number>
z.set(z.string()) // Set<string>typescript
// Record:键和值均为指定类型的对象
z.record(z.string()) // { [key: string]: string }
z.record(z.string(), z.number()) // { [key: string]: number }
// 部分记录(部分键可选)
z.partialRecord(z.enum(["a", "b"]), z.string())
// Map
z.map(z.string(), z.number()) // Map<string, number>
z.set(z.string()) // Set<string>Advanced Patterns
高级模式
Load for complete advanced validation and transformation patterns.
references/advanced-patterns.md加载以获取完整的高级验证与转换模式文档。
references/advanced-patterns.mdQuick Reference
快速参考
Refinements (custom validation):
typescript
z.string().refine((val) => val.length >= 8, "Too short");
z.object({ password, confirmPassword }).superRefine((data, ctx) => { /* ... */ });Transformations (modify data):
typescript
z.string().transform((val) => val.trim());
z.string().pipe(z.coerce.number());Codecs (bidirectional transforms - NEW in v4.1):
typescript
const DateCodec = z.codec(
z.iso.datetime(),
z.date(),
{
decode: (str) => new Date(str),
encode: (date) => date.toISOString(),
}
);Recursive Types:
typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({ name: z.string(), subcategories: z.array(CategorySchema) })
);Optional/Nullable:
typescript
z.string().optional() // string | undefined
z.string().nullable() // string | null
z.string().default("default") // Provides default if undefinedReadonly & Brand:
typescript
z.object({ ... }).readonly() // Readonly properties
z.string().brand<"UserId">() // Nominal typing→ Load for: Complete refinement patterns, async validation, codec examples, composable schemas, conditional validation, performance optimization
references/advanced-patterns.md细化验证(自定义验证):
typescript
z.string().refine((val) => val.length >= 8, "Too short");
z.object({ password, confirmPassword }).superRefine((data, ctx) => { /* ... */ });转换(修改数据):
typescript
z.string().transform((val) => val.trim());
z.string().pipe(z.coerce.number());Codec(双向转换 - v4.1新增):
typescript
const DateCodec = z.codec(
z.iso.datetime(),
z.date(),
{
decode: (str) => new Date(str),
encode: (date) => date.toISOString(),
}
);递归类型:
typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({ name: z.string(), subcategories: z.array(CategorySchema) })
);可选/可空:
typescript
z.string().optional() // string | undefined
z.string().nullable() // string | null
z.string().default("default") // 当值为undefined时使用默认值只读与品牌类型:
typescript
z.object({ ... }).readonly() // 只读属性
z.string().brand<"UserId">() // 标称类型→ 加载查看: 完整的细化验证模式、异步验证、Codec示例、可组合Schema、条件验证、性能优化
references/advanced-patterns.mdError Handling
错误处理
Load for complete error formatting and customization guide.
references/error-handling.md加载以获取完整的错误格式化与自定义指南。
references/error-handling.mdQuick Reference
快速参考
Error Formatting Methods:
typescript
// For forms
const { fieldErrors } = z.flattenError(error);
// For nested data
const tree = z.treeifyError(error);
const nameError = tree.properties?.user?.properties?.name?.errors?.[0];
// For debugging
console.log(z.prettifyError(error));Custom Error Messages (three levels):
typescript
// 1. Schema-level (highest priority)
z.string({ error: "Custom message" });
z.string().min(5, "Too short");
// 2. Per-parse level
schema.parse(data, { error: (issue) => ({ message: "..." }) });
// 3. Global level
z.config({ customError: (issue) => ({ message: "..." }) });Localization (40+ languages):
typescript
z.config(z.locales.es()); // Spanish
z.config(z.locales.fr()); // French→ Load for: Complete error formatting examples, custom error patterns, localization setup, error code reference
references/error-handling.md错误格式化方法:
typescript
// 适用于表单
const { fieldErrors } = z.flattenError(error);
// 适用于嵌套数据
const tree = z.treeifyError(error);
const nameError = tree.properties?.user?.properties?.name?.errors?.[0];
// 适用于调试
console.log(z.prettifyError(error));自定义错误消息(三个层级):
typescript
// 1. Schema层级(优先级最高)
z.string({ error: "Custom message" });
z.string().min(5, "Too short");
// 2. 解析层级
schema.parse(data, { error: (issue) => ({ message: "..." }) });
// 3. 全局层级
z.config({ customError: (issue) => ({ message: "..." }) });本地化(支持40+种语言):
typescript
z.config(z.locales.es()); // 西班牙语
z.config(z.locales.fr()); // 法语→ 加载查看: 完整的错误格式化示例、自定义错误模式、本地化设置、错误代码参考
references/error-handling.mdType Inference
类型推断
Load for complete type inference and metadata documentation.
references/type-inference.md加载以获取完整的类型推断与元数据文档。
references/type-inference.mdQuick Reference
快速参考
Basic Type Inference:
typescript
const UserSchema = z.object({ name: z.string() });
type User = z.infer<typeof UserSchema>; // { name: string }Input vs Output (for transforms):
typescript
const TransformSchema = z.string().transform((s) => s.length);
type Input = z.input<typeof TransformSchema>; // string
type Output = z.output<typeof TransformSchema>; // numberJSON Schema Conversion:
typescript
const jsonSchema = z.toJSONSchema(UserSchema, {
target: "openapi-3.0",
metadata: true,
});Metadata:
typescript
// Add metadata
const EmailSchema = z.string().email().meta({
title: "Email Address",
description: "User's email address",
});
// Create custom registry
const formRegistry = z.registry<FormFieldMeta>();→ Load for: Complete type inference patterns, JSON Schema options, metadata system, custom registries, brand types
references/type-inference.md基础类型推断:
typescript
const UserSchema = z.object({ name: z.string() });
type User = z.infer<typeof UserSchema>; // { name: string }输入与输出类型(针对转换操作):
typescript
const TransformSchema = z.string().transform((s) => s.length);
type Input = z.input<typeof TransformSchema>; // string
type Output = z.output<typeof TransformSchema>; // numberJSON Schema转换:
typescript
const jsonSchema = z.toJSONSchema(UserSchema, {
target: "openapi-3.0",
metadata: true,
});元数据:
typescript
// 添加元数据
const EmailSchema = z.string().email().meta({
title: "Email Address",
description: "User's email address",
});
// 创建自定义注册表
const formRegistry = z.registry<FormFieldMeta>();→ 加载查看: 完整的类型推断模式、JSON Schema选项、元数据系统、自定义注册表、品牌类型
references/type-inference.mdFunctions
函数验证
Validate function inputs and outputs:
typescript
const AddFunction = z.function()
.args(z.number(), z.number()) // Arguments
.returns(z.number()); // Return type
// Implement typed function
const add = AddFunction.implement((a, b) => {
return a + b; // Type-checked!
});
// Async functions
const FetchFunction = z.function()
.args(z.string())
.returns(z.promise(z.object({ data: z.any() })))
.implementAsync(async (url) => {
const response = await fetch(url);
return response.json();
});验证函数的输入与输出:
typescript
const AddFunction = z.function()
.args(z.number(), z.number()) // 参数类型
.returns(z.number()); // 返回值类型
// 实现带类型检查的函数
const add = AddFunction.implement((a, b) => {
return a + b; // 具备类型检查!
});
// 异步函数
const FetchFunction = z.function()
.args(z.string())
.returns(z.promise(z.object({ data: z.any() })))
.implementAsync(async (url) => {
const response = await fetch(url);
return response.json();
});Common Patterns
常见使用模式
Environment Variables
环境变量验证
typescript
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().int().positive().default(3000),
API_KEY: z.string().min(32),
});
// Validate on startup
const env = EnvSchema.parse(process.env);
// Now use typed env
console.log(env.PORT); // numbertypescript
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]),
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().int().positive().default(3000),
API_KEY: z.string().min(32),
});
// 启动时验证
const env = EnvSchema.parse(process.env);
// 现在可以使用带类型的env
console.log(env.PORT); // number类型API Request Validation
API请求验证
typescript
const CreateUserRequest = z.object({
username: z.string().min(3).max(20),
email: z.string().email(),
password: z.string().min(8),
age: z.number().int().positive().optional(),
});
// Express example
app.post("/users", async (req, res) => {
const result = CreateUserRequest.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
errors: z.flattenError(result.error).fieldErrors,
});
}
const user = await createUser(result.data);
res.json(user);
});typescript
const CreateUserRequest = z.object({
username: z.string().min(3).max(20),
email: z.string().email(),
password: z.string().min(8),
age: z.number().int().positive().optional(),
});
// Express示例
app.post("/users", async (req, res) => {
const result = CreateUserRequest.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
errors: z.flattenError(result.error).fieldErrors,
});
}
const user = await createUser(result.data);
res.json(user);
});Form Validation
表单验证
typescript
const FormSchema = z.object({
firstName: z.string().min(1, "First name required"),
lastName: z.string().min(1, "Last name required"),
email: z.string().email("Invalid email"),
age: z.coerce.number().int().min(18, "Must be 18+"),
agreeToTerms: z.literal(true, {
errorMap: () => ({ message: "Must accept terms" }),
}),
});
type FormData = z.infer<typeof FormSchema>;typescript
const FormSchema = z.object({
firstName: z.string().min(1, "First name required"),
lastName: z.string().min(1, "Last name required"),
email: z.string().email("Invalid email"),
age: z.coerce.number().int().min(18, "Must be 18+"),
agreeToTerms: z.literal(true, {
errorMap: () => ({ message: "Must accept terms" }),
}),
});
type FormData = z.infer<typeof FormSchema>;Partial Updates
部分更新
typescript
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
// For PATCH requests: make everything optional except id
const UpdateUserSchema = UserSchema.partial().required({ id: true });
type UpdateUser = z.infer<typeof UpdateUserSchema>;
// { id: string; name?: string; email?: string }typescript
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
// 用于PATCH请求:除id外所有字段设为可选
const UpdateUserSchema = UserSchema.partial().required({ id: true });
type UpdateUser = z.infer<typeof UpdateUserSchema>;
// { id: string; name?: string; email?: string }Composable Schemas
可组合Schema
typescript
// Base schemas
const TimestampSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
});
const AuthorSchema = z.object({
authorId: z.string(),
authorName: z.string(),
});
// Compose into larger schemas
const PostSchema = z.object({
id: z.string(),
title: z.string(),
content: z.string(),
}).merge(TimestampSchema).merge(AuthorSchema);typescript
// 基础Schema
const TimestampSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
});
const AuthorSchema = z.object({
authorId: z.string(),
authorName: z.string(),
});
// 组合为更大的Schema
const PostSchema = z.object({
id: z.string(),
title: z.string(),
content: z.string(),
}).merge(TimestampSchema).merge(AuthorSchema);Ecosystem Integration
生态系统集成
Load for complete framework and tooling integration guide.
references/ecosystem-integrations.md加载以获取完整的框架与工具集成指南。
references/ecosystem-integrations.mdQuick Reference
快速参考
ESLint Plugins:
- - Enforces best practices
eslint-plugin-zod-x - - Enforces import style
eslint-plugin-import-zod
Framework Integrations:
- tRPC - End-to-end typesafe APIs
- React Hook Form - Form validation (see skill)
react-hook-form-zod - Prisma - Generate Zod from database models
- NestJS - DTOs and validation pipes
Code Generation:
- orval - OpenAPI → Zod
- Hey API - OpenAPI to TypeScript + Zod
- kubb - API toolkit with codegen
→ Load for: Setup instructions, integration examples, Hono middleware, Drizzle ORM patterns
references/ecosystem-integrations.mdESLint插件:
- - 强制执行最佳实践
eslint-plugin-zod-x - - 规范导入风格
eslint-plugin-import-zod
框架集成:
- tRPC - 端到端类型安全API
- React Hook Form - 表单验证(查看技能)
react-hook-form-zod - Prisma - 从数据库模型生成Zod Schema
- NestJS - DTO与验证管道
代码生成:
- orval - OpenAPI → Zod
- Hey API - OpenAPI转TypeScript + Zod
- kubb - 带代码生成的API工具包
→ 加载查看: 设置说明、集成示例、Hono中间件、Drizzle ORM模式
references/ecosystem-integrations.mdTroubleshooting
故障排除
Load for complete troubleshooting guide, performance tips, and best practices.
references/troubleshooting.md加载以获取完整的故障排除指南、性能优化技巧与最佳实践。
references/troubleshooting.mdQuick Reference
快速参考
Common Issues:
- TypeScript strict mode required → Enable in
tsconfig.json - Large bundle size → Use for code splitting
z.lazy() - Slow async refinements → Cache or debounce
- Circular dependencies → Use
z.lazy() - Slow unions → Use
z.discriminatedUnion() - Transform vs refine confusion → Use for validation,
.refine()for modification.transform()
Performance Tips:
- Use (5-10x faster than
.discriminatedUnion()).union() - Cache schema instances
- Use (avoids try-catch overhead)
.safeParse() - Lazy load large schemas
Best Practices:
- Define schemas at module level
- Use type inference ()
z.infer - Add custom error messages
- Validate at system boundaries
- Compose small schemas
- Document with
.meta()
→ Load for: Detailed solutions, performance optimization, best practices, testing patterns
references/troubleshooting.md常见问题:
- 要求TypeScript严格模式 → 在中启用
tsconfig.json - 包体积过大 → 使用进行代码拆分
z.lazy() - 异步细化验证缓慢 → 缓存或防抖
- 循环依赖 → 使用
z.lazy() - 联合类型性能差 → 使用
z.discriminatedUnion() - 混淆transform与refine → 使用进行验证,
.refine()进行数据修改.transform()
性能优化技巧:
- 使用(比
.discriminatedUnion()快5-10倍).union() - 缓存Schema实例
- 使用(避免try-catch开销)
.safeParse() - 懒加载大型Schema
最佳实践:
- 在模块级别定义Schema
- 使用类型推断()
z.infer - 添加自定义错误消息
- 在系统边界处进行验证
- 组合小型Schema
- 使用添加文档
.meta()
→ 加载查看: 详细解决方案、性能优化、最佳实践、测试模式
references/troubleshooting.mdQuick Reference
快速参考
typescript
// Primitives
z.string(), z.number(), z.boolean(), z.date(), z.bigint()
// Collections
z.array(), z.tuple(), z.object(), z.record(), z.map(), z.set()
// Special types
z.enum(), z.union(), z.discriminatedUnion(), z.intersection()
z.literal(), z.any(), z.unknown(), z.never()
// Modifiers
.optional(), .nullable(), .nullish(), .default(), .catch()
.readonly(), .brand()
// Validation
.min(), .max(), .length(), .regex(), .email(), .url(), .uuid()
.refine(), .superRefine()
// Transformation
.transform(), .pipe(), .codec()
// Parsing
.parse(), .safeParse(), .parseAsync(), .safeParseAsync()
// Type inference
z.infer<typeof Schema>, z.input<typeof Schema>, z.output<typeof Schema>
// Error handling
z.flattenError(), z.treeifyError(), z.prettifyError()
// JSON Schema
z.toJSONSchema(schema, options)
// Metadata
.meta(), .describe()
// Object methods
.extend(), .pick(), .omit(), .partial(), .required(), .merge()typescript
// 原始类型
z.string(), z.number(), z.boolean(), z.date(), z.bigint()
// 集合类型
z.array(), z.tuple(), z.object(), z.record(), z.map(), z.set()
// 特殊类型
z.enum(), z.union(), z.discriminatedUnion(), z.intersection()
z.literal(), z.any(), z.unknown(), z.never()
// 修饰符
.optional(), .nullable(), .nullish(), .default(), .catch()
.readonly(), .brand()
// 验证方法
.min(), .max(), .length(), .regex(), .email(), .url(), .uuid()
.refine(), .superRefine()
// 转换方法
.transform(), .pipe(), .codec()
// 解析方法
.parse(), .safeParse(), .parseAsync(), .safeParseAsync()
// 类型推断
z.infer<typeof Schema>, z.input<typeof Schema>, z.output<typeof Schema>
// 错误处理
z.flattenError(), z.treeifyError(), z.prettifyError()
// JSON Schema
z.toJSONSchema(schema, options)
// 元数据
.meta(), .describe()
// 对象方法
.extend(), .pick(), .omit(), .partial(), .required(), .merge()When to Load References
何时加载参考文档
Load when:
references/migration-guide.md- Upgrading from Zod v3 to v4
- Questions about breaking changes
- Need migration checklist or rollback strategy
- Errors related to deprecated APIs (,
.merge(), etc.)error.format() - Number validation issues with or unsafe integers
Infinity
Load when:
references/error-handling.md- Need to format errors for forms or UI
- Implementing custom error messages
- Questions about ,
z.flattenError(), orz.treeifyError()z.prettifyError() - Setting up localization for error messages
- Need error code reference or pattern examples
Load when:
references/advanced-patterns.md- Implementing custom refinements or async validation
- Need bidirectional transformations (codecs)
- Working with recursive types or self-referential data
- Questions about ,
.refine(), or.transform().codec() - Need performance optimization patterns
- Implementing conditional validation
Load when:
references/type-inference.md- Questions about TypeScript type inference
- Need to generate JSON Schema for OpenAPI or AI
- Implementing metadata system for forms or documentation
- Need custom registries for type-safe metadata
- Questions about ,
z.infer,z.inputz.output - Using brand types for ID safety
Load when:
references/ecosystem-integrations.md- Integrating with tRPC, React Hook Form, Prisma, or NestJS
- Setting up ESLint plugins for best practices
- Generating Zod schemas from OpenAPI (orval, Hey API, kubb)
- Questions about Hono middleware or Drizzle ORM
- Need framework-specific integration examples
Load when:
references/troubleshooting.md- Encountering TypeScript strict mode errors
- Bundle size concerns or lazy loading needs
- Performance issues with large unions or async refinements
- Questions about circular dependencies
- Need best practices or testing patterns
- Confusion between and
.refine().transform()
加载的场景:
references/migration-guide.md- 从Zod v3升级到v4
- 关于破坏性变更的疑问
- 需要迁移清单或回滚策略
- 遇到已弃用API相关错误(如、
.merge()等)error.format() - 数字验证中出现或不安全整数相关问题
Infinity
加载的场景:
references/error-handling.md- 需要为表单或UI格式化错误
- 实现自定义错误消息
- 关于、
z.flattenError()或z.treeifyError()的疑问z.prettifyError() - 为错误消息设置本地化
- 需要错误代码参考或模式示例
加载的场景:
references/advanced-patterns.md- 实现自定义细化验证或异步验证
- 需要双向转换(Codec)
- 处理递归类型或自引用数据
- 关于、
.refine()或.transform()的疑问.codec() - 需要性能优化模式
- 实现条件验证
加载的场景:
references/type-inference.md- 关于TypeScript类型推断的疑问
- 需要为OpenAPI/AI生成JSON Schema
- 为表单或文档实现元数据系统
- 需要用于类型安全元数据的自定义注册表
- 关于、
z.infer、z.input的疑问z.output - 使用品牌类型保障ID安全
加载的场景:
references/ecosystem-integrations.md- 与tRPC、React Hook Form、Prisma或NestJS集成
- 设置ESLint插件以遵循最佳实践
- 从OpenAPI生成Zod Schema(orval、Hey API、kubb)
- 关于Hono中间件或Drizzle ORM的疑问
- 需要框架特定的集成示例
加载的场景:
references/troubleshooting.md- 遇到TypeScript严格模式错误
- 包体积过大或需要懒加载
- 大型联合类型或异步细化验证的性能问题
- 关于循环依赖的疑问
- 需要最佳实践或测试模式
- 混淆与
.refine().transform()
Additional Resources
额外资源
- Official Docs: https://zod.dev
- GitHub: https://github.com/colinhacks/zod
- TypeScript Playground: https://zod-playground.vercel.app
- ESLint Plugin (Best Practices): https://github.com/JoshuaKGoldberg/eslint-plugin-zod-x
- tRPC Integration: https://trpc.io
- Ecosystem: https://zod.dev/ecosystem
Production Notes:
- Package version: 4.1.12+ (Zod 4.x stable)
- Zero dependencies
- Bundle size: 2kb (gzipped)
- TypeScript 5.5+ required
- Strict mode required
- Last verified: 2025-11-17
- Skill version: 2.0.0 (Updated with v4.1 enhancements)
What's New in This Version:
- ✨ Comprehensive v3 to v4 migration guide with breaking changes
- ✨ Enhanced error customization with three-level system
- ✨ Expanded metadata API with registry system
- ✨ Improved error formatting with practical examples
- ✨ Built-in localization support for 40+ locales
- ✨ Detailed codec documentation with real-world patterns
- ✨ Performance improvements and architectural changes explained
- 官方文档: https://zod.dev
- GitHub: https://github.com/colinhacks/zod
- TypeScript Playground: https://zod-playground.vercel.app
- ESLint插件(最佳实践): https://github.com/JoshuaKGoldberg/eslint-plugin-zod-x
- tRPC集成: https://trpc.io
- 生态系统: https://zod.dev/ecosystem
生产环境注意事项:
- 包版本: 4.1.12+(Zod 4.x稳定版)
- 零依赖
- 包体积: 2kb(压缩后)
- 要求TypeScript 5.5+
- 要求启用严格模式
- 最后验证时间: 2025-11-17
- 技能版本: 2.0.0(已更新v4.1增强特性)
本版本新增内容:
- ✨ 完整的v3到v4迁移指南,包含破坏性变更说明
- ✨ 三级系统的增强型错误自定义
- ✨ 带注册表系统的扩展元数据API
- ✨ 实用示例的改进型错误格式化
- ✨ 内置对40+种语言的本地化支持
- ✨ 带真实场景的详细Codec文档
- ✨ 性能优化与架构变更说明