Tuples
Zod provides functionality for creating and validating tuples. Tuples are arrays with fixed lengths where each position can have a different type.
Basic Usage
ts
import { z } from "zod";
// Create a tuple schema
const StringNumberTuple = z.tuple([z.string(), z.number()]);
type StringNumberTuple = z.infer<typeof StringNumberTuple>; // [string, number]
// Validation
StringNumberTuple.parse(["hello", 42]); // passes
StringNumberTuple.parse(["hello", "world"]); // fails
StringNumberTuple.parse([42, 42]); // fails
Rest Elements
You can use the .rest()
method to specify the type of remaining elements:
ts
const StringNumberRest = z.tuple([z.string(), z.number()]).rest(z.boolean());
// Validation
StringNumberRest.parse(["hello", 42]); // passes
StringNumberRest.parse(["hello", 42, true]); // passes
StringNumberRest.parse(["hello", 42, true, false]); // passes
StringNumberRest.parse(["hello", 42, "true"]); // fails
Complex Tuples
Tuples can contain any Zod schema:
ts
// Object tuples
const UserTuple = z.tuple([
z.object({ id: z.string() }),
z.object({ name: z.string() }),
]);
// Union tuples
const UnionTuple = z.tuple([
z.union([z.string(), z.number()]),
z.boolean(),
]);
// Nested tuples
const NestedTuple = z.tuple([
z.tuple([z.string(), z.number()]),
z.boolean(),
]);
Tuple Length
Tuple length is fixed (unless using .rest()
):
ts
const Tuple = z.tuple([z.string(), z.number()]);
Tuple.parse(["hello", 42]); // passes
Tuple.parse(["hello"]); // fails: tuple too short
Tuple.parse(["hello", 42, true]); // fails: tuple too long
Tuple Element Access
You can access tuple elements using array indices:
ts
const Tuple = z.tuple([z.string(), z.number(), z.boolean()]);
// In 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
Custom Error Messages
You can provide custom error messages for each tuple element:
ts
const Tuple = z.tuple([
z.string({
invalid_type_error: "First element must be a string",
}),
z.number({
invalid_type_error: "Second element must be a number",
}),
]);
// Validation
Tuple.parse([42, "hello"]); // fails with custom error messages