教程 zod tutorial

Unions

Zod 提供了内置的 z.union 方法来创建联合类型。

基本用法

ts
import { z } from "zod";

// 创建联合类型
const stringOrNumber = z.union([z.string(), z.number()]);

stringOrNumber.parse("hello"); // 通过
stringOrNumber.parse(42);      // 通过
stringOrNumber.parse(true);    // 失败

使用 .or() 方法

为了方便,你也可以使用 .or() 方法:

ts
const stringOrNumber = z.string().or(z.number());
const stringOrNumberOrBoolean = z.string()
  .or(z.number())
  .or(z.boolean());

判别联合类型

判别联合类型是指联合类型中的每个成员都有一个共同的、具有不同值的属性:

ts
const result = z.discriminatedUnion("status", [
  z.object({
    status: z.literal("success"),
    data: z.string(),
  }),
  z.object({
    status: z.literal("error"),
    error: z.instanceof(Error),
  }),
]);

// 验证成功的情况
result.parse({
  status: "success",
  data: "成功了!",
}); // 通过

// 验证错误的情况
result.parse({
  status: "error",
  error: new Error("出错了"),
}); // 通过

访问联合选项

你可以使用 .options 属性获取联合类型的所有选项:

ts
const myUnion = z.discriminatedUnion("status", [
  z.object({ status: z.literal("loading") }),
  z.object({ status: z.literal("success") }),
  z.object({ status: z.literal("error") }),
]);

console.log(myUnion.options); // 获取所有选项

合并判别联合类型

要合并两个或更多判别联合类型,可以展开它们的 .options:

ts
const A = z.discriminatedUnion("status", [
  z.object({ status: z.literal("loading") }),
  z.object({ status: z.literal("success") }),
]);

const B = z.discriminatedUnion("status", [
  z.object({ status: z.literal("error") }),
  z.object({ status: z.literal("timeout") }),
]);

const Combined = z.discriminatedUnion("status", [
  ...A.options,
  ...B.options,
]);

错误处理

对于判别联合类型,Zod 会根据判别字段的值来确定使用哪个模式进行验证,这样可以提供更精确的错误信息:

ts
const result = z.discriminatedUnion("status", [
  z.object({
    status: z.literal("success"),
    data: z.string(),
  }),
  z.object({
    status: z.literal("error"),
    message: z.string(),
  }),
]);

// 当提供了错误的字段时
result.parse({
  status: "success",
  message: "这不应该在这里", // 错误:success 状态应该有 data 字段
}); // 将抛出特定的错误