教程 zod tutorial

Tuples

Zod 提供了创建和验证元组的功能。元组是固定长度的数组,其中每个位置可以有不同的类型。

基本用法

ts
import { z } from "zod";

// 创建元组模式
const StringNumberTuple = z.tuple([z.string(), z.number()]);
type StringNumberTuple = z.infer<typeof StringNumberTuple>; // [string, number]

// 验证
StringNumberTuple.parse(["hello", 42]); // 通过
StringNumberTuple.parse(["hello", "world"]); // 失败
StringNumberTuple.parse([42, 42]); // 失败

可选元素

你可以使用 .rest() 方法来指定剩余元素的类型:

ts
const StringNumberRest = z.tuple([z.string(), z.number()]).rest(z.boolean());

// 验证
StringNumberRest.parse(["hello", 42]); // 通过
StringNumberRest.parse(["hello", 42, true]); // 通过
StringNumberRest.parse(["hello", 42, true, false]); // 通过
StringNumberRest.parse(["hello", 42, "true"]); // 失败

复杂元组

元组可以包含任何 Zod 模式:

ts
// 对象元组
const UserTuple = z.tuple([
  z.object({ id: z.string() }),
  z.object({ name: z.string() }),
]);

// 联合类型元组
const UnionTuple = z.tuple([
  z.union([z.string(), z.number()]),
  z.boolean(),
]);

// 嵌套元组
const NestedTuple = z.tuple([
  z.tuple([z.string(), z.number()]),
  z.boolean(),
]);

元组长度

元组的长度是固定的(除非使用 .rest()):

ts
const Tuple = z.tuple([z.string(), z.number()]);

Tuple.parse(["hello", 42]); // 通过
Tuple.parse(["hello"]); // 失败:元组太短
Tuple.parse(["hello", 42, true]); // 失败:元组太长

元组元素访问

你可以使用数组索引访问元组的元素:

ts
const Tuple = z.tuple([z.string(), z.number(), z.boolean()]);

// 在 TypeScript 中
type First = z.infer<typeof Tuple>[0]; // string
type Second = z.infer<typeof Tuple>[1]; // number
type Third = z.infer<typeof Tuple>[2]; // boolean

自定义错误消息

你可以为元组的每个元素提供自定义错误消息:

ts
const Tuple = z.tuple([
  z.string({
    invalid_type_error: "第一个元素必须是字符串",
  }),
  z.number({
    invalid_type_error: "第二个元素必须是数字",
  }),
]);

// 验证
Tuple.parse([42, "hello"]); // 失败,带有自定义错误消息