Skip to main content

Basic Usage

Create an array schema that validates each element.
import { z } from 'zod';

const StringArray = z.array(z.string());

StringArray.parse(['a', 'b', 'c']); // ✓ Valid
StringArray.parse(['a', 1, 'c']);   // ✗ Invalid - contains number

type StringArray = z.infer<typeof StringArray>;
// string[]

Signature

function array<T extends SomeType>(
  element: T,
  params?: string | ZodArrayParams
): ZodArray<T>
element
ZodType
required
The schema to validate each array element against.
params
string | ZodArrayParams
Optional error message (string) or configuration object.

Properties

element
ZodType
Access the element schema.
const schema = z.array(z.string());
schema.element; // ZodString

Methods

min()

Set a minimum length for the array.
const AtLeastThree = z.array(z.string()).min(3);

AtLeastThree.parse(['a', 'b', 'c']);     // ✓ Valid
AtLeastThree.parse(['a', 'b']);          // ✗ Invalid - too short
AtLeastThree.parse(['a', 'b', 'c', 'd']); // ✓ Valid
Signature:
min(minLength: number, params?: string | ZodCheckMinLengthParams): this
minLength
number
required
Minimum number of elements required.
params
string | object
Optional error message or configuration object.
z.array(z.string()).min(3, 'At least 3 items required')
z.array(z.string()).min(3, { message: 'Too few items' })

max()

Set a maximum length for the array.
const AtMostFive = z.array(z.number()).max(5);

AtMostFive.parse([1, 2, 3]);           // ✓ Valid
AtMostFive.parse([1, 2, 3, 4, 5]);     // ✓ Valid
AtMostFive.parse([1, 2, 3, 4, 5, 6]);  // ✗ Invalid - too long
Signature:
max(maxLength: number, params?: string | ZodCheckMaxLengthParams): this
maxLength
number
required
Maximum number of elements allowed.
params
string | object
Optional error message or configuration object.
z.array(z.number()).max(5, 'Too many items')
z.array(z.number()).max(5, { message: 'Maximum 5 items' })

length()

Set an exact length for the array.
const ExactlyThree = z.array(z.boolean()).length(3);

ExactlyThree.parse([true, false, true]); // ✓ Valid
ExactlyThree.parse([true, false]);       // ✗ Invalid - wrong length
ExactlyThree.parse([true, false, true, false]); // ✗ Invalid - wrong length
Signature:
length(len: number, params?: string | ZodCheckLengthEqualsParams): this
len
number
required
Exact number of elements required.
params
string | object
Optional error message or configuration object.
z.array(z.boolean()).length(3, 'Must have exactly 3 items')

nonempty()

Require at least one element (equivalent to .min(1)).
const NonEmptyArray = z.array(z.string()).nonempty();

NonEmptyArray.parse(['item']);  // ✓ Valid
NonEmptyArray.parse([]);        // ✗ Invalid - empty array

type NonEmptyArray = z.infer<typeof NonEmptyArray>;
// [string, ...string[]]
The inferred type becomes a tuple type [T, ...T[]] to ensure at least one element at the type level.
Signature:
nonempty(params?: string | ZodCheckMinLengthParams): this
params
string | object
Optional error message or configuration object.
z.array(z.string()).nonempty('Array cannot be empty')

unwrap()

Access the element schema.
const StringArray = z.array(z.string());
const ElementSchema = StringArray.unwrap();

type Element = z.infer<typeof ElementSchema>;
// string
Signature:
unwrap(): T

Combining Validations

You can chain multiple validation methods:
const BoundedArray = z.array(z.number())
  .min(2, 'Need at least 2 numbers')
  .max(10, 'Cannot exceed 10 numbers');

BoundedArray.parse([1, 2, 3]);  // ✓ Valid
BoundedArray.parse([1]);         // ✗ Invalid - too short
BoundedArray.parse([...Array(11).fill(0)]); // ✗ Invalid - too long

Complex Element Types

Arrays can contain any Zod schema:

Objects

const Users = z.array(
  z.object({
    id: z.string(),
    name: z.string(),
    email: z.string().email(),
  })
);

type Users = z.infer<typeof Users>;
// Array<{ id: string; name: string; email: string }>

Nested Arrays

const Matrix = z.array(z.array(z.number()));

type Matrix = z.infer<typeof Matrix>;
// number[][]

Matrix.parse([
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
]); // ✓ Valid

Unions

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

type MixedArray = z.infer<typeof MixedArray>;
// (string | number)[]

MixedArray.parse(['a', 1, 'b', 2]); // ✓ Valid

Convenience Method

You can also create arrays using the .array() method on any schema:
const StringArray = z.string().array();
// Equivalent to: z.array(z.string())

const MinThreeStrings = z.string().array().min(3);
// Equivalent to: z.array(z.string()).min(3)

Type Inference

const schema = z.array(z.string()).min(1).max(10);

type Output = z.infer<typeof schema>;
// string[] (with runtime validation for 1-10 elements)

type Input = z.input<typeof schema>;
// string[] (same as output for arrays without transformations)

Refinements

Add custom validation logic:
const UniqueNumbers = z.array(z.number())
  .refine(
    (arr) => new Set(arr).size === arr.length,
    'Array must contain unique values'
  );

UniqueNumbers.parse([1, 2, 3]);    // ✓ Valid
UniqueNumbers.parse([1, 2, 2, 3]); // ✗ Invalid - duplicate values
const SortedArray = z.array(z.number())
  .min(2)
  .refine(
    (arr) => arr.every((val, i, a) => i === 0 || val >= a[i - 1]),
    'Array must be sorted in ascending order'
  );

SortedArray.parse([1, 2, 3, 4]); // ✓ Valid
SortedArray.parse([1, 3, 2, 4]); // ✗ Invalid - not sorted
  • z.tuple() - For fixed-length arrays with specific types
  • z.set() - For sets with unique values
  • z.record() - For key-value collections

Build docs developers (and LLMs) love