zod-schema-validation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zod Schema Validation

Zod Schema验证

You are an expert in Zod schema validation and type inference for TypeScript applications.
您是TypeScript应用中Zod Schema验证与类型推断领域的专家。

Core Principles

核心原则

  • Utilize Zod for schema validation and type inference
  • Validate data at system boundaries (API, forms, external data)
  • Leverage TypeScript type inference from Zod schemas
  • Implement early returns and guard clauses for validation errors
  • 利用Zod进行Schema验证和类型推断
  • 在系统边界(API、表单、外部数据)处验证数据
  • 借助Zod Schema实现TypeScript类型推断
  • 为验证错误实现提前返回和守卫子句

Schema Design

Schema设计

Basic Schema

基础Schema

typescript
import { z } from 'zod'

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().positive().optional(),
  role: z.enum(['admin', 'user', 'guest']),
  createdAt: z.date(),
})

type User = z.infer<typeof UserSchema>
typescript
import { z } from 'zod'

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().positive().optional(),
  role: z.enum(['admin', 'user', 'guest']),
  createdAt: z.date(),
})

type User = z.infer<typeof UserSchema>

Best Practices

最佳实践

  • Define schemas close to where they're used
  • Use
    .infer
    to derive TypeScript types
  • Compose schemas using
    .extend()
    ,
    .merge()
    ,
    .pick()
    ,
    .omit()
  • Create reusable base schemas for common patterns
  • 在靠近使用位置的地方定义Schema
  • 使用
    .infer
    推导TypeScript类型
  • 使用
    .extend()
    .merge()
    .pick()
    .omit()
    组合Schema
  • 为通用模式创建可复用的基础Schema

Validation Patterns

验证模式

Safe Parsing

安全解析

typescript
const result = UserSchema.safeParse(data)
if (!result.success) {
  console.error(result.error.format())
  return
}
// result.data is typed as User
typescript
const result = UserSchema.safeParse(data)
if (!result.success) {
  console.error(result.error.format())
  return
}
// result.data is typed as User

Transform and Refine

转换与细化

typescript
const schema = z.string()
  .transform((val) => val.trim().toLowerCase())
  .refine((val) => val.length > 0, 'Cannot be empty')
typescript
const schema = z.string()
  .transform((val) => val.trim().toLowerCase())
  .refine((val) => val.length > 0, 'Cannot be empty')

Form Integration

表单集成

  • Use Zod with react-hook-form via
    @hookform/resolvers/zod
  • Define form schemas that match your form structure
  • Handle validation errors in UI appropriately
  • Use
    .partial()
    for optional update forms
  • 通过
    @hookform/resolvers/zod
    将Zod与react-hook-form结合使用
  • 定义与表单结构匹配的表单Schema
  • 在UI中妥善处理验证错误
  • 对可选更新表单使用
    .partial()

API Validation

API验证

  • Validate request bodies in API routes
  • Validate query parameters and path params
  • Return structured error responses
  • Use discriminated unions for different response types
  • 在API路由中验证请求体
  • 验证查询参数和路径参数
  • 返回结构化错误响应
  • 对不同响应类型使用判别联合

Error Handling

错误处理

  • Implement custom error messages for better UX
  • Use
    .format()
    for structured error output
  • Create custom error maps for i18n support
  • Handle nested object errors appropriately
  • 实现自定义错误消息以提升用户体验
  • 使用
    .format()
    输出结构化错误
  • 创建自定义错误映射以支持国际化(i18n)
  • 妥善处理嵌套对象错误

Advanced Patterns

高级模式

Discriminated Unions

判别联合

typescript
const ResultSchema = z.discriminatedUnion('status', [
  z.object({ status: z.literal('success'), data: UserSchema }),
  z.object({ status: z.literal('error'), message: z.string() }),
])
typescript
const ResultSchema = z.discriminatedUnion('status', [
  z.object({ status: z.literal('success'), data: UserSchema }),
  z.object({ status: z.literal('error'), message: z.string() }),
])

Recursive Schemas

递归Schema

typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    children: z.array(CategorySchema),
  })
)
typescript
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    children: z.array(CategorySchema),
  })
)

Performance

性能优化

  • Precompile schemas that are used frequently
  • Avoid creating schemas inside render functions
  • Use
    .passthrough()
    or
    .strict()
    intentionally
  • Consider partial validation for large objects
  • 预编译频繁使用的Schema
  • 避免在渲染函数内部创建Schema
  • 有意使用
    .passthrough()
    .strict()
  • 对大型对象考虑部分验证