Zod Cheatsheet
Quick reference for Zod schema validation — primitives, objects, arrays, unions, transforms, and error handling.
Installation & Import
npm install zod
import { z } from 'zod';Primitive Types
z.string()
z.number()
z.boolean()
z.bigint()
z.date()
z.null()
z.undefined()
z.void()
z.any()
z.unknown()
z.never()String Validations
z.string().min(3)
z.string().max(100)
z.string().length(10)
z.string().email()
z.string().url()
z.string().uuid()
z.string().regex(/^[a-z]+$/)
z.string().includes("foo")
z.string().startsWith("http")
z.string().endsWith(".com")
z.string().trim()
z.string().toLowerCase()
z.string().toUpperCase()Number Validations
z.number().min(0)
z.number().max(100)
z.number().int()
z.number().positive()
z.number().negative()
z.number().nonnegative()
z.number().multipleOf(5)
z.number().finite()
z.number().safe() // Number.MIN_SAFE_INTEGER to MAX_SAFE_INTEGERObjects
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email().optional(),
});
// Infer TypeScript type
type User = z.infer<typeof UserSchema>;
// Parse (throws on invalid)
const user = UserSchema.parse(data);
// Safe parse (returns { success, data } or { success, error })
const result = UserSchema.safeParse(data);
if (result.success) console.log(result.data);
// Partial — all fields optional
UserSchema.partial();
// Pick / Omit
UserSchema.pick({ id: true, name: true });
UserSchema.omit({ email: true });
// Extend
UserSchema.extend({ role: z.string() });
// Merge
UserSchema.merge(OtherSchema);Arrays
z.array(z.string())
z.array(z.number()).min(1)
z.array(z.number()).max(10)
z.array(z.number()).length(3)
z.array(z.number()).nonempty()
// Tuple — fixed-length, typed positions
z.tuple([z.string(), z.number()])
z.tuple([z.string(), z.number()]).rest(z.boolean())Unions & Intersections
// Union
z.union([z.string(), z.number()])
// shorthand
z.string().or(z.number())
// Discriminated union (more efficient parsing)
z.discriminatedUnion("type", [
z.object({ type: z.literal("circle"), radius: z.number() }),
z.object({ type: z.literal("square"), side: z.number() }),
]);
// Intersection
z.intersection(SchemaA, SchemaB)
// shorthand
SchemaA.and(SchemaB)
// Enum
z.enum(["admin", "user", "guest"])
z.nativeEnum(MyEnum) // TypeScript enumOptional, Nullable, Default
z.string().optional() // string | undefined
z.string().nullable() // string | null
z.string().nullish() // string | null | undefined
z.string().default("anon") // use default if undefined
z.string().catch("fallback") // use fallback on parse errorTransforms & Refinements
// Transform output
z.string().transform(val => val.toUpperCase())
// Refine with custom validation
z.string().refine(val => val.length > 3, {
message: "Must be longer than 3 characters",
})
// superRefine for multiple issues
z.object({ start: z.date(), end: z.date() }).superRefine((val, ctx) => {
if (val.end < val.start) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "end must be after start" });
}
})
// Preprocess input before parsing
z.preprocess(val => Number(val), z.number())Error Handling
const result = schema.safeParse(data);
if (!result.success) {
// Flat error map
console.log(result.error.flatten());
// { fieldErrors: { name: ["Required"] }, formErrors: [] }
// Full error details
result.error.issues.forEach(issue => {
console.log(issue.path, issue.message);
});
}
// Custom error messages
z.string({ required_error: "Name is required" })
z.string().min(3, { message: "At least 3 characters" })Frequently Asked Questions
What is Zod used for?
Zod is a TypeScript-first schema validation library. It validates data at runtime — API responses, form inputs, environment variables — and automatically infers TypeScript types from schemas so you only define the shape once.
What is the difference between parse and safeParse in Zod?
parse() throws a ZodError if validation fails. safeParse() returns { success: true, data } or { success: false, error } without throwing. Use safeParse() when you want to handle errors gracefully instead of catching exceptions.
How do I get TypeScript types from a Zod schema?
Use z.infer<typeof YourSchema>. Example: const UserSchema = z.object({ name: z.string() }); type User = z.infer<typeof UserSchema>. The TypeScript type is derived from the schema automatically — no need to write it separately.
Can Zod validate nested objects and arrays?
Yes. Nest z.object() schemas inside other schemas for nested objects. Use z.array(schema) for arrays. Zod recursively validates each level and reports errors with the full dot-notation path.
How do I handle optional and nullable fields in Zod?
Use .optional() for fields that can be undefined, .nullable() for fields that can be null, and .nullish() for fields that can be both. Use .default(value) to provide a fallback when the field is undefined.
From the blog
View all →
Jun 8, 2026
JavaScript Object to JSON: Serialization Patterns and Common Pitfalls

Jun 8, 2026
TypeScript to JavaScript: When and How to Strip Types

Jun 4, 2026
JavaScript Object to JSON: Serialization Patterns and Common Pitfalls

Jun 4, 2026
TypeScript to JavaScript: When and How to Strip Types

Jun 1, 2026
JSON to TypeScript: Auto-Generate Interfaces from API Responses
Generate a Zod schema from JSON automatically?
Use the JSON to Zod Converter →