Zod Cheat Sheet

Quick reference for Zod schema validation library. Primitives, objects, arrays, transforms, refinements, error handling, and integration patterns — all in one page.

Primitive Types String Validations Number Validations Objects Arrays & Tuples Unions, Enums & Literals Transforms & Refinements Parsing & Error Handling Type Inference Common Patterns

Primitive Types

z.string() String schema
z.number() Number schema (includes floats)
z.bigint() BigInt schema
z.boolean() Boolean schema
z.date() Date object schema
z.undefined() Undefined schema
z.null() Null schema
z.void() Void (undefined) schema
z.any() Any type (bypasses validation)
z.unknown() Unknown type (safer than any)
z.never() Never type (always fails)

String Validations

z.string().min(5) Minimum length
z.string().max(100) Maximum length
z.string().length(10) Exact length
z.string().email() Valid email format
z.string().url() Valid URL format
z.string().uuid() Valid UUID format
z.string().regex(/^[a-z]+$/) Custom regex pattern
z.string().trim() Trim whitespace before validation
z.string().toLowerCase() Transform to lowercase
z.string().startsWith("https://") Must start with prefix
z.string().includes("@") Must contain substring
z.string().datetime() ISO 8601 datetime string

Number Validations

z.number().int() Must be integer
z.number().positive() Must be > 0
z.number().negative() Must be < 0
z.number().nonnegative() Must be >= 0
z.number().min(1) Minimum value (inclusive)
z.number().max(100) Maximum value (inclusive)
z.number().multipleOf(5) Must be multiple of
z.number().finite() Must be finite
z.number().safe() Within safe integer range

Objects

z.object({ name: z.string() }) Object schema with shape
.extend({ age: z.number() }) Add fields to existing schema
.merge(otherSchema) Merge two object schemas
.pick({ name: true }) Pick specific fields
.omit({ password: true }) Omit specific fields
.partial() Make all fields optional
.required() Make all fields required
.passthrough() Allow unknown keys
.strict() Error on unknown keys
.strip() Remove unknown keys (default)
z.object({}).catchall(z.string()) Type for unknown keys

Arrays & Tuples

z.array(z.string()) Array of strings
z.string().array() Equivalent shorthand
.min(1) Non-empty array
.max(10) Max 10 elements
.length(5) Exactly 5 elements
.nonempty() At least 1 element (narrows type)
z.tuple([z.string(), z.number()]) Fixed-length typed tuple
z.tuple([z.string()]).rest(z.number()) Tuple with rest elements

Unions, Enums & Literals

z.union([z.string(), z.number()]) Union type (string | number)
z.discriminatedUnion("type", [...]) Tagged union (faster parsing)
z.enum(["admin", "user", "guest"]) String enum
z.nativeEnum(MyEnum) Use TypeScript enum
z.literal("active") Exact literal value
z.literal(42) Literal number

Transforms & Refinements

.transform((val) => val.trim()) Transform parsed value
.refine((val) => val > 0, "Must be positive") Custom validation rule
.superRefine((val, ctx) => { ... }) Advanced validation with context
z.preprocess((val) => Number(val), z.number()) Transform before parsing
.default("hello") Default value if undefined
.catch("fallback") Fallback value if parsing fails
.optional() Make optional (T | undefined)
.nullable() Make nullable (T | null)
.nullish() Optional + nullable (T | null | undefined)

Parsing & Error Handling

schema.parse(data) Parse or throw ZodError
schema.safeParse(data) Parse → { success, data?, error? }
schema.parseAsync(data) Async parse (for async refinements)
schema.safeParseAsync(data) Async safe parse
error.issues Array of validation issues
error.format() Nested error object
error.flatten() Flat { formErrors, fieldErrors }
z.ZodError Error class for type checking

Type Inference

z.infer Extract TypeScript type from schema
z.input Input type (before transforms)
z.output Output type (after transforms)
type User = z.infer Common pattern: derive types from schemas

Common Patterns

const envSchema = z.object({ PORT: z.coerce.number() }) Environment variable validation
z.coerce.number() Coerce string → number
z.coerce.boolean() Coerce to boolean
z.coerce.date() Coerce string → Date
z.record(z.string(), z.number()) Record
z.map(z.string(), z.number()) Map
z.set(z.string()) Set
z.promise(z.string()) Promise
z.lazy(() => CategorySchema) Recursive / self-referencing schema

Try It Live

Test these patterns with our free JSON Schema Validator. No signup needed.

Open JSON Schema Validator →
Step-by-Step Guide

How to Validate Email Addresses

Read Guide →

More Cheat Sheets