This skill provides comprehensive patterns for using Zod validation library in TypeScript applications. It ensures input validation is done correctly, securely, and consistently across the codebase.
Use this skill when: Working with user input validation, API request validation, form data validation, or data transformation in Quetrex.
This skill provides comprehensive patterns for using Zod validation library in TypeScript applications. It ensures input validation is done correctly, securely, and consistently across the codebase.
Schema Patterns - Complete guide to all Zod schema types
Error Handling - Robust error management
Refinements - Custom validation logic
Transforms - Data transformation and normalization
Async Validation - Asynchronous validation patterns
Type Inference - TypeScript type extraction
API Integration - Next.js integration patterns
Common Schemas - Reusable schema library
import { z } from 'zod'
// Define schema
const userSchema = z.object({
email: z.string().email(),
age: z.number().int().positive(),
role: z.enum(['admin', 'user'])
})
// Parse data (throws on error)
const user = userSchema.parse(data)
// Safe parse (returns result object)
const result = userSchema.safeParse(data)
if (result.success) {
console.log(result.data)
} else {
console.error(result.error)
}
// Extract TypeScript type from schema
type User = z.infer<typeof userSchema>
// { email: string; age: number; role: 'admin' | 'user' }
// src/app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
const createUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8)
})
export async function POST(request: NextRequest) {
const body = await request.json()
const result = createUserSchema.safeParse(body)
if (!result.success) {
return NextResponse.json(
{ error: 'Validation failed', details: result.error.format() },
{ status: 400 }
)
}
// Process validated data
const { email, password } = result.data
// ...
}
safeParse() over parse() for better error handlingcommon-schemas.mdz.infer<typeof schema> for TypeScript typesconst configSchema = z.object({
timeout: z.number().int().positive().default(30),
retries: z.number().int().min(0).default(3),
debug: z.boolean().optional()
})
const addressSchema = z.object({
country: z.string(),
state: z.string().optional()
}).refine(
data => data.country === 'US' ? !!data.state : true,
{ message: 'State is required for US addresses', path: ['state'] }
)
const emailSchema = z.string()
.trim()
.toLowerCase()
.email()
const eventSchema = z.discriminatedUnion('type', [
z.object({ type: z.literal('click'), x: z.number(), y: z.number() }),
z.object({ type: z.literal('keypress'), key: z.string() })
])
const usernameSchema = z.string()
.min(3)
.max(20)
.regex(/^[a-zA-Z0-9_-]+$/)
.refine(async (username) => {
const existing = await db.user.findUnique({ where: { username } })
return !existing
}, { message: 'Username already taken' })
All schemas must work with TypeScript strict mode:
any types@ts-ignore commentsz.inferValidation logic requires comprehensive tests:
'use server'
import { z } from 'zod'
const createProjectSchema = z.object({
name: z.string().min(1).max(100),
description: z.string().optional()
})
export async function createProject(formData: FormData) {
const result = createProjectSchema.safeParse({
name: formData.get('name'),
description: formData.get('description')
})
if (!result.success) {
return { error: result.error.format() }
}
// Process validated data
return { success: true, data: result.data }
}
Start with:
Then explore:
Last updated: 2025-11-23 | Zod v4.1.12