使用 Zod 构建 TypeScript 类型安全的 Schema 验证

解决 TypeScript 开发中“定义两次”的痛点:通过 Zod 定义一次 Schema,同时获得运行时校验逻辑和静态类型推断,消除接口定义与验证代码不一致的问题。

为什么需要这个技能

在标准的 TypeScript 开发中,我们通常需要编写一个 interface 来定义类型,再编写一段验证逻辑(如 if 判断)来确保运行时数据正确。这种重复劳动不仅低效,且在 API 变更时极易导致两端不一致。

Zod 实现了“Schema 即类型”。它允许你定义一个验证模式,并使用 z.infer 自动提取出对应的 TypeScript 类型。这意味着你只需维护一份代码,即可在编译时获得类型提示,在运行时确保数据安全。

适用场景

  • API 输入验证:对请求体(Request Body)或查询参数进行严格校验。
  • 表单校验:结合 React Hook Form 实现端到端的类型安全表单。
  • 环境变量管理:验证 process.env 是否包含所有必要的配置项,防止应用启动后崩溃。
  • 数据清洗与转换:将字符串形式的输入(如 FormData)自动转换为数字或日期对象。
  • 复杂业务逻辑校验:实现跨字段验证(如确认密码一致性)。

核心工作流

1. 定义 Schema 与类型推断

使用 Zod 的原生类型定义规则,并通过 z.infer 导出类型,避免手动编写 interface。

import { z } from "zod";

const UserSchema = z.object({
  id: z.string().uuid(),
  username: z.string().min(3),
  role: z.enum(["ADMIN", "USER"]).default("USER"),
  age: z.coerce.number().min(18), // 将输入强制转换为数字
});

export type User = z.infer<typeof UserSchema>;

2. 执行解析与错误处理

推荐使用 safeParse 代替 parse,通过结果对象的 success 状态进行分支处理,避免大量的 try-catch 块。

const result = UserSchema.safeParse(inputData);

if (!result.success) {
  // 提取可序列化的错误信息
  console.log(result.error.flatten().fieldErrors);
} else {
  const validData = result.data; // 此处 validData 已具有完全的类型定义
}

3. 高级校验与转换

利用 .refine 实现自定义逻辑,使用 .transform 在验证通过后改变数据形态。

const passwordSchema = z.object({
  password: z.string().min(8),
  confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
  message: "两次输入的密码不一致",
  path: ["confirmPassword"], 
});

下载和安装

下载 zod-validation-expert 中文版 Skill ZIP

解压后将目录放入你的 AI 工具 skills 文件夹,重启工具后即可使用。具体路径参考内附的 USAGE.zh.md

你可能还需要

暂无推荐