Web Dev

Zod.js parse方法

2025年1月2日 (5个月前)

zodparse 函数是用于 数据验证和类型安全解析 的核心方法,它根据预先定义的 schema 检查输入数据是否符合预期格式.


1. 核心功能

  • 验证:检查输入数据是否匹配 schema 规则。
  • 转换:将输入数据转换为符合 TypeScript 的类型。
  • 错误处理:自动抛出详细的验证错误(ZodError)。

2. 基础用法

(1) 定义 Schema

import { z } from "zod";

// 定义用户数据schema
const UserSchema = z.object({
  id: z.number().int().positive(),
  name: z.string().min(2),
  email: z.string().email(),
  age: z.number().min(18).optional(),
});

(2) 使用 parse 验证

const rawData = { id: 1, name: "Alice", email: "alice@example.com" };

try {
  const user = UserSchema.parse(rawData);
  // user 类型被推断为:
  // { id: number; name: string; email: string; age?: number }
  console.log("验证通过:", user);
} catch (error) {
  console.error("验证失败:", error.errors);
}

(3) 错误输出示例

如果 rawData = { id: "1", name: "A", email: "invalid" },会抛出:

{
  "issues": [
    {
      "code": "invalid_type",
      "expected": "number",
      "received": "string",
      "path": ["id"],
      "message": "Expected number, received string"
    },
    {
      "code": "too_small",
      "minimum": 2,
      "type": "string",
      "path": ["name"],
      "message": "String must contain at least 2 character(s)"
    },
    {
      "code": "invalid_string",
      "validation": "email",
      "path": ["email"],
      "message": "Invalid email"
    }
  ]
}

3. 高级用法

(1) 安全解析(不抛出异常)

使用 safeParse

const result = UserSchema.safeParse(rawData);
if (result.success) {
  console.log(result.data); // 验证通过的数据
} else {
  console.log(result.error); // ZodError 对象
}

(2) 组合 Schema

const AddressSchema = z.object({
  street: z.string(),
  city: z.string(),
});

const UserWithAddressSchema = UserSchema.extend({
  address: AddressSchema,
});

(3) 异步验证

const AsyncSchema = z.string().refine(async (val) => {
  return await checkUsernameAvailability(val);
}, "用户名已存在");

const result = await AsyncSchema.safeParseAsync("alice");

(4) 自定义错误消息

const PasswordSchema = z
  .string()
  .min(8, "密码至少8位")
  .regex(/[A-Z]/, "必须包含大写字母");

4. 实用场景

(1) API 请求验证

// 定义API响应schema
const ApiResponseSchema = z.object({
  success: z.boolean(),
  data: z.unknown().optional(),
  error: z.string().optional(),
});

fetch("/api/user")
  .then((res) => res.json())
  .then((json) => ApiResponseSchema.parse(json))
  .then((data) => {
    /* 类型安全的数据 */
  });

(2) 表单验证

// React Hook Form 集成示例
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

const form = useForm({
  resolver: zodResolver(UserSchema),
  defaultValues: { name: "", email: "" },
});

(3) 环境变量验证

const EnvSchema = z.object({
  DATABASE_URL: z.string().url(),
  API_KEY: z.string().min(32),
  NODE_ENV: z.enum(["development", "production"]),
});

EnvSchema.parse(process.env); // 启动时验证环境变量

5. 性能优化

  • 预编译 Schema:对高频调用的 schema 提前编译:
    const validateUser = UserSchema.parse;
    // 后续直接调用 validateUser(data)
    
  • 选择性校验:用 pick/omit 创建子 schema 减少校验范围:
    const LoginSchema = UserSchema.pick({ email: true });

6. 错误处理最佳实践

try {
  const data = schema.parse(input);
} catch (err) {
  if (err instanceof z.ZodError) {
    // 转换为前端友好格式
    const errors = err.issues.map((issue) => ({
      field: issue.path.join("."),
      message: issue.message,
    }));
    showToast(errors);
  }
}

总结

  • 核心方法parse() 是 Zod 进行数据验证的入口。
  • 核心价值
    • 将动态数据转换为静态类型
    • 替代手动编写验证逻辑
  • 适用场景:表单、API、配置验证等所有需要数据校验的场景。