Zod 是一个 TypeScript-first 的验证库,特别适用于类型安全的表单和数据验证。它为开发者提供了一种声明式的方式来验证数据,同时与 TypeScript 的类型系统完美集成。

Zod 文档概述

1. 安装 Zod

你可以通过 npm 或 yarn 安装 Zod:

npm install zod
# 或者
yarn add zod

2. 基础用法

Zod 使用 z 对象提供不同的验证器,可以验证不同的数据类型。最基本的用法是创建模式(schema),并通过它来验证数据。

import { z } from 'zod';

// 创建一个字符串模式,要求字符串必须是电子邮件格式
const emailSchema = z.string().email();

// 测试数据
const result = emailSchema.safeParse('example@example.com');
if (result.success) {
  console.log('Valid email');
} else {
  console.log('Invalid email');
}

3. 常见数据验证器

Zod 提供了一些常用的验证方法,可以验证各种常见的数据类型,包括:

  • 字符串 (z.string())
  • 数字 (z.number())
  • 布尔值 (z.boolean())
  • 数组 (z.array())
  • 对象 (z.object())
  • 联合类型 (z.union())
// 字符串验证
const usernameSchema = z.string().min(3).max(20);

// 数字验证
const ageSchema = z.number().int().min(18).max(100);

// 布尔值验证
const isActiveSchema = z.boolean();

// 数组验证
const numbersSchema = z.array(z.number()).min(1).max(5);

// 对象验证
const userSchema = z.object({
  name: z.string().min(1),
  age: z.number().int().min(18),
});

4. 联合验证

Zod 支持联合验证,允许将多种验证规则结合在一起:

const stringOrNumber = z.union([z.string(), z.number()]);

const test = stringOrNumber.safeParse(123);  // Valid
const test2 = stringOrNumber.safeParse('hello');  // Valid
const test3 = stringOrNumber.safeParse(true);  // Invalid

5. 嵌套对象验证

你可以将验证规则嵌套到对象内:

const userSchema = z.object({
  name: z.string().min(1),
  age: z.number().int().min(18),
  address: z.object({
    street: z.string(),
    city: z.string(),
  }),
});

const userData = {
  name: 'John Doe',
  age: 25,
  address: {
    street: '123 Main St',
    city: 'Somewhere',
  },
};

const result = userSchema.safeParse(userData);
console.log(result.success ? 'Valid user' : 'Invalid user');

6. 条件验证(refinement)

有时候,你可能需要根据某些条件来进一步验证数据。这时可以使用 .refine() 方法:

const ageSchema = z.number().min(18).refine(val => val % 2 === 0, {
  message: 'Age must be an even number',
});

const result = ageSchema.safeParse(19);  // Invalid, as it's not even
console.log(result.error);  // "Age must be an even number"

7. 自定义错误消息

你可以在验证规则中添加自定义错误消息,帮助用户更容易理解验证失败的原因。

const emailSchema = z
  .string()
  .email('Invalid email address')
  .min(1, 'Email cannot be empty');

const result = emailSchema.safeParse('');
if (!result.success) {
  console.log(result.error.errors);  // Logs custom error message
}

8. 异步验证

Zod 也支持异步验证,例如用来验证某些数据是否存在于数据库中,或是其他需要异步操作的场景。

const asyncSchema = z
  .string()
  .refine(async (value) => {
    const exists = await checkIfEmailExistsInDB(value); // 假设此函数是异步的
    return !exists;
  }, {
    message: 'Email already exists',
  });

asyncSchema.safeParseAsync('test@example.com').then(result => {
  console.log(result.success ? 'Valid email' : 'Invalid email');
});

9. .safeParse() vs .parse()

  • safeParse():返回一个对象,包含 successerror 字段,可以用来检查验证是否成功,且不会抛出异常。
  • parse():如果验证失败,会抛出一个异常。如果验证成功,会返回验证后的值。
// safeParse 示例
const result = usernameSchema.safeParse('John123');
if (!result.success) {
  console.log(result.error);
}

// parse 示例
try {
  const data = usernameSchema.parse('John123');
  console.log(data);  // 成功时返回数据
} catch (e) {
  console.error(e.errors);  // 失败时抛出异常
}

10. 完整示例:表单验证

以下是一个结合 Zod 验证表单输入的简单示例:

import { z } from 'zod';

// 创建表单验证 schema
const formSchema = z.object({
  username: z.string().min(3, 'Username must be at least 3 characters'),
  age: z.number().min(18, 'You must be at least 18 years old'),
  email: z.string().email('Invalid email address'),
});

// 模拟表单数据
const formData = {
  username: 'John',
  age: 25,
  email: 'john.doe@example.com',
};

// 验证表单数据
const result = formSchema.safeParse(formData);

if (result.success) {
  console.log('Form is valid');
} else {
  console.log('Form validation failed', result.error.errors);
}

参考文档:

Zod 是一个非常强大的库,特别适合 TypeScript 项目,它能帮助开发者以类型安全的方式进行表单验证、数据验证以及业务逻辑验证。

文章目录