Overview
Want to master Zod schema validation through code? This by-example tutorial provides 80 heavily annotated examples covering 95% of Zod's API. Learn runtime validation, type inference, transforms, refinements, and production integration patterns through working code rather than lengthy explanations.
What Is By-Example Learning?
By-example learning is a code-first approach where you learn concepts through annotated, working examples rather than narrative explanations. Each example shows:
- What the code does - Brief explanation of the Zod concept
- How it works - A focused, heavily commented code example
- Key Takeaway - A pattern summary highlighting the key takeaway
- Why It Matters - Production context, when to use, deeper significance
This approach works best when you already understand TypeScript fundamentals and have experience building applications. You learn Zod's schema model, validation patterns, and type inference by studying real code rather than theoretical descriptions.
What Is Zod?
Zod is a TypeScript-first schema declaration and validation library that bridges the gap between TypeScript's compile-time type safety and runtime data validation. Key distinctions:
- TypeScript-first: Schemas automatically infer TypeScript types — no duplicate type definitions
- Runtime validation: Validates data that TypeScript cannot see at compile time (API responses, user input, environment variables)
- Zero dependencies: Ships with no external dependencies; minimal bundle impact
- Composable: Schemas compose into complex validators through chaining, merging, and nesting
- Ecosystem integration: First-class support for tRPC, React Hook Form, Next.js, and most TypeScript frameworks
Learning Path
graph TD
A["Beginner<br/>Zod Fundamentals<br/>Examples 1-28"] --> B["Intermediate<br/>Production Patterns<br/>Examples 29-55"]
B --> C["Advanced<br/>Expert Mastery<br/>Examples 56-80"]
D["0%<br/>No Zod Knowledge"] -.-> A
C -.-> E["95%<br/>Zod Mastery"]
style A fill:#0173B2,color:#fff
style B fill:#DE8F05,color:#fff
style C fill:#029E73,color:#fff
style D fill:#CC78BC,color:#fff
style E fill:#029E73,color:#fff
Coverage Philosophy: 95% Through 80 Examples
The 95% coverage means you'll understand Zod deeply enough to validate any production data with confidence. It doesn't mean you'll know every edge case or internal API — those come with experience.
The 80 examples are organized progressively:
- Beginner (Examples 1-28): Foundation schemas (primitives, objects, arrays, enums, unions, optionals, nullables, defaults, tuples, records, maps, sets, dates, type inference, parse vs safeParse)
- Intermediate (Examples 29-55): Production patterns (refinements, transforms, preprocessors, pipes, discriminated unions, recursive schemas, lazy schemas, custom errors, schema composition, form validation, API validation, coercion)
- Advanced (Examples 56-80): Expert mastery (branded types, custom ZodType, OpenAPI integration, tRPC integration, React Hook Form integration, performance optimization, conditional schemas, generic schemas, custom error maps, z.function(), effect schemas, migration patterns)
Together, these examples cover 95% of what you'll use in production TypeScript applications.
Annotation Density: 1-2.25 Comments Per Code Line
CRITICAL: All examples maintain 1-2.25 comment lines per code line PER EXAMPLE to ensure deep understanding.
What this means:
- Simple lines get 1 annotation explaining purpose or result
- Complex lines get 2+ annotations explaining behavior, types, and side effects
- Use
// =>notation to show expected values, outputs, or inferred types
Example:
import { z } from "zod";
const UserSchema = z.object({
// => Creates ZodObject schema
name: z.string(), // => name field: string, required
age: z.number().min(0), // => age field: number, must be >= 0
// => min(0) adds runtime constraint
});
type User = z.infer<typeof UserSchema>; // => Extracts TypeScript type from schema
// => User = { name: string; age: number }
const result = UserSchema.safeParse({ name: "Aisha", age: 28 });
// => safeParse: returns { success: true, data: ... } or { success: false, error: ... }
// => Does NOT throw — safe for handling invalid data
if (result.success) {
console.log(result.data.name); // => Output: "Aisha"
// => TypeScript narrows result.data to User
}This density ensures each example is self-contained and fully comprehensible without external documentation.
Structure of Each Example
All examples follow a consistent five-part format:
### Example N: Descriptive Title
2-3 sentence explanation of the concept.
```typescript
// Heavily annotated code example
// showing the Zod pattern in action
Key Takeaway: 1-2 sentence summary.
Why It Matters: 50-100 words explaining significance in production applications.
**Code annotations**:
- `// =>` shows inferred types, expected output, validation results
- Inline comments explain what each schema method does
- Variable names are self-documenting
- Type annotations make data flow explicit
## What's Covered
### Primitive Schemas
- **Strings**: `z.string()`, string methods (min, max, email, url, uuid, regex)
- **Numbers**: `z.number()`, number methods (min, max, int, positive, negative)
- **Booleans**: `z.boolean()`, boolean coercion
- **Dates**: `z.date()`, date range validation
- **Literals**: `z.literal()`, exact value matching
- **Enums**: `z.enum()`, `z.nativeEnum()`, enum access
### Composite Schemas
- **Objects**: `z.object()`, strict/strip/passthrough modes
- **Arrays**: `z.array()`, length constraints, non-empty arrays
- **Tuples**: `z.tuple()`, fixed-length typed arrays
- **Records**: `z.record()`, typed key-value pairs
- **Maps**: `z.map()`, typed Map structures
- **Sets**: `z.set()`, typed Set structures
### Schema Modifiers
- **Optional/Nullable**: `.optional()`, `.nullable()`, `.nullish()`
- **Defaults**: `.default()`, `.catch()`
- **Union Types**: `z.union()`, discriminated unions
- **Intersections**: `z.intersection()`, schema merging
### Validation and Parsing
- **Parse Methods**: `.parse()`, `.safeParse()`, `.parseAsync()`, `.safeParseAsync()`
- **Type Inference**: `z.infer<>`, `z.input<>`, `z.output<>`
- **Error Handling**: `ZodError`, error formatting, custom error messages
- **Refinements**: `.refine()`, `.superRefine()`, cross-field validation
### Transforms and Preprocessing
- **Transforms**: `.transform()`, data reshaping and mapping
- **Preprocessing**: `z.preprocess()`, input coercion
- **Pipes**: `.pipe()`, schema chaining
- **Coercion**: `z.coerce.*`, automatic type conversion
### Schema Composition
- **Object Methods**: `.merge()`, `.extend()`, `.pick()`, `.omit()`, `.partial()`, `.required()`
- **Recursive Schemas**: `z.lazy()`, recursive data structures
- **Schema Utilities**: `.and()`, `.or()`, `.brand()`, `.readonly()`
### Production Integration
- **Form Validation**: React Hook Form + Zod integration
- **API Validation**: Request/response schema validation
- **tRPC Integration**: Schema-first API definition
- **OpenAPI**: Schema to OpenAPI spec generation
### Advanced Patterns
- **Branded Types**: Type-safe nominal typing
- **Custom ZodType**: Extending Zod with custom validators
- **Generic Schemas**: Reusable parameterized schemas
- **z.function()**: Function schema validation
- **Custom Error Maps**: Global error customization
- **Effect Schemas**: `.transform()` with effects pattern
## What's NOT Covered
We exclude topics that belong in specialized tutorials:
- **Zod Internals**: Parser implementation details, AST traversal
- **Alternative Libraries**: Yup, io-ts, Valibot comparisons (brief migration examples only)
- **Build Configuration**: TypeScript strict mode setup (assumed)
- **Framework Internals**: Next.js, tRPC source code
- **Advanced TypeScript**: Conditional types, mapped types unrelated to Zod
For these topics, see dedicated tutorials and the official Zod documentation.
## Prerequisites
### Required
- **TypeScript fundamentals**: Types, interfaces, generics, type inference
- **ES6+ JavaScript**: Destructuring, spread operators, async/await
- **npm/module system**: Package installation and imports
- **Programming experience**: You've built TypeScript applications before
### Recommended
- **React basics**: Helpful for form validation examples
- **REST API concepts**: Helpful for API validation examples
- **tRPC awareness**: Helpful for advanced integration examples
### Not Required
- **Zod experience**: This guide assumes you're new to Zod
- **Advanced TypeScript**: We explain TypeScript patterns as needed
- **Functional programming**: Helpful but not required
## Getting Started
Before starting the examples, ensure Zod is installed:
```bash
npm install zod
All examples use import { z } from "zod" and are runnable in a TypeScript environment (Node.js with tsx or ts-node, or browser with bundler).
# Run examples directly with tsx
npx tsx example.tsHow to Use This Guide
1. Choose Your Starting Point
- New to Zod? Start with Beginner (Example 1)
- Know basic schemas? Start with Intermediate (Example 29)
- Building production integration? Jump to Advanced (Example 56)
2. Read the Example
Each example has five parts:
- Explanation (2-3 sentences): What Zod concept, why it exists, when to use it
- Code (heavily commented): Working TypeScript code showing the pattern
- Key Takeaway (1-2 sentences): Distilled essence of the pattern
- Why It Matters (50-100 words): Production context and deeper significance
3. Run the Code
Create a test file and run each example:
mkdir zod-examples && cd zod-examples
npm init -y
npm install zod tsx typescript
# Paste example code into example.ts
npx tsx example.ts4. Modify and Experiment
Change schemas, add invalid data, break validations on purpose. Experimentation builds intuition faster than reading.
5. Reference as Needed
Use this guide as a reference when building features. Search for relevant examples and adapt patterns to your code.
Ready to Start?
Choose your learning path:
- Beginner - Start here if new to Zod. Build foundation understanding through 28 core examples.
- Intermediate - Jump here if you know basic schemas. Master production patterns through 27 examples.
- Advanced - Expert mastery through 25 advanced examples covering integrations, branded types, and optimization.
Or jump to specific topics by searching for relevant example keywords (parse, refine, transform, form, API, branded, tRPC, etc.).
Examples by Level
Beginner (Examples 1–28)
- Example 1: String Schema
- Example 2: Number Schema
- Example 3: Boolean Schema
- Example 4: String Validations
- Example 5: Number Validations
- Example 6: Literal Schema
- Example 7: Date Schema
- Example 8: Object Schema
- Example 9: Nested Object Schema
- Example 10: Array Schema
- Example 11: Tuple Schema
- Example 12: Optional Schema
- Example 13: Nullable Schema
- Example 14: Default Values
- Example 15: Catch (Fallback on Error)
- Example 16: Enum Schema
- Example 17: Union Schema
- Example 18: Optional and Nullable Combined
- Example 19: Record Schema
- Example 20: Map Schema
- Example 21: Set Schema
- Example 22: parse vs safeParse
- Example 23: Type Inference with z.infer
- Example 24: ZodError Structure
- Example 25: Async Validation
- Example 26: Schema Intersection
- Example 27: Schema Branching with .or()
- Example 28: Schema Reuse and Composition
Intermediate (Examples 29–55)
- Example 29: Basic Refinement with .refine()
- Example 30: superRefine for Multiple Errors
- Example 31: Transform Values
- Example 32: Preprocess
- Example 33: Pipeline with .pipe()
- Example 34: Discriminated Union
- Example 35: Coercion with z.coerce
- Example 36: Recursive Schemas with z.lazy()
- Example 37: Custom Error Messages
- Example 38: Error Formatting
- Example 39: Object Schema Methods — merge and extend
- Example 40: Object Schema Methods — pick and omit
- Example 41: Partial and Required
- Example 42: Schema Validation Methods — keyof and shape
- Example 43: Form Validation Pattern
- Example 44: API Request Validation
- Example 45: API Response Validation
- Example 46: Environment Variable Validation
- Example 47: Branded Types
- Example 48: Discriminated Union Advanced Pattern
- Example 49: Schema Composition with .and()
- Example 50: Conditional Validation with superRefine
- Example 51: Custom Error Map
- Example 52: z.function() Schema
- Example 53: Readonly Schema
- Example 54: Schema from Unknown Data
- Example 55: Schema Introspection
Advanced (Examples 56–80)
- Example 56: Custom ZodType
- Example 57: Generic Schema Factory
- Example 58: Schema-to-OpenAPI with zod-to-json-schema
- Example 59: tRPC Integration
- Example 60: React Hook Form Integration
- Example 61: Next.js Server Action Validation
- Example 62: Schema Caching and Reuse
- Example 63: Lazy Validation with safeParse
- Example 64: Batch Validation
- Example 65: Runtime Type Guards with Zod
- Example 66: Composable Validation Middleware
- Example 67: Versioned Schema Migration
- Example 68: Dynamic Schema Generation
- Example 69: Memoized Validation Results
- Example 70: Schema from TypeScript Types (Reverse Inference)
- Example 71: Migrating from Yup
- Example 72: Migrating from io-ts
- Example 73: Effect Schemas (Advanced Transform Pattern)
- Example 74: Schema Registry Pattern
- Example 75: Complete Production Schema Architecture
- Example 76: Testing Schemas
- Example 77: Advanced Error Path Navigation
- Example 78: Schema Cloning and Modification
- Example 79: Zod with Drizzle ORM Integration
- Example 80: Building a Schema-First API Layer
Last updated March 24, 2026