zod

Zod - Quick Reference

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "zod" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-zod

Zod - Quick Reference

When to Use This Skill

  • Form validation with React Hook Form

  • API data parsing/validation

  • Type inference from schemas

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: zod for comprehensive documentation.

Essential Patterns

Basic Schema

import { z } from 'zod';

const userSchema = z.object({ name: z.string().min(2), email: z.string().email(), age: z.number().min(18).optional(), role: z.enum(['admin', 'user']) });

// Type inference type User = z.infer<typeof userSchema>;

// Parse const user = userSchema.parse(data); // throws ZodError const result = userSchema.safeParse(data); // { success, data/error }

Common Validations

// String z.string().min(1).max(100).email().url().uuid()

// Number z.number().int().positive().min(0).max(100)

// Custom validation z.string().refine(val => val.startsWith('@'), "Must start with @")

// Object cross-field z.object({ password: z.string(), confirm: z.string() }).refine(d => d.password === d.confirm, { message: "Passwords don't match", path: ['confirm'] });

React Hook Form

import { zodResolver } from '@hookform/resolvers/zod';

const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(userSchema) });

<input {...register('name')} /> {errors.name && <span>{errors.name.message}</span>}

Schema Operations

userSchema.partial() // All fields optional userSchema.pick({ name: true }) // Pick fields userSchema.omit({ id: true }) // Omit fields userSchema.extend({ phone: z.string() }) // Extend

When NOT to Use This Skill

  • Yup existing projects - Use yup skill for Formik integration

  • NestJS DTOs - Use class-validator skill for decorator-based validation

  • Compile-time only checks - TypeScript types are sufficient

  • Simple PropTypes - React PropTypes might be enough

Anti-Patterns to Avoid

  • Do not define schemas inside components (performance)

  • Do not use .parse() for user input without try/catch

  • Do not forget custom error messages

Anti-Patterns

Anti-Pattern Why It's Bad Correct Approach

Schema inside components Re-created on every render Define at module level

Using .parse() without try-catch Throws unhandled errors Use .safeParse() for user input

No custom error messages Generic "Invalid input" Add custom messages to all validations

Validating twice (FE + BE) Performance waste Share schemas between client/server

Not using z.infer Manual type definitions Always use type inference

Ignoring .transform() Miss data normalization Use transforms for trimming, etc.

Quick Troubleshooting

Issue Cause Solution

"Expected string, received number" Type mismatch Use z.coerce.string() for type coercion

Performance issues Schema in component Move schema to module level

Async validation not working Using .parse() Use .parseAsync() for async refinements

Nested errors not showing Not using flatten() Use error.flatten() for nested structures

"Invalid type" on optional fields Using undefined Use .optional() or .nullable()

Form not validating Resolver not set Add resolver: zodResolver(schema)

Production Readiness

Error Handling

import { z, ZodError } from 'zod';

// Safe parsing with error handling function validateInput<T>(schema: z.ZodSchema<T>, data: unknown): T { const result = schema.safeParse(data);

if (!result.success) { const errors = result.error.flatten(); throw new ValidationError(errors); }

return result.data; }

// Custom error messages const userSchema = z.object({ email: z.string({ required_error: 'Email is required', invalid_type_error: 'Email must be a string', }).email({ message: 'Invalid email format' }),

password: z.string() .min(8, { message: 'Password must be at least 8 characters' }) .regex(/[A-Z]/, { message: 'Password must contain uppercase letter' }) .regex(/[0-9]/, { message: 'Password must contain number' }), });

// Error formatting for API responses function formatZodError(error: ZodError): Record<string, string[]> { return error.flatten().fieldErrors as Record<string, string[]>; }

API Integration

// Express middleware import { Request, Response, NextFunction } from 'express';

function validate<T extends z.ZodSchema>(schema: T) { return (req: Request, res: Response, next: NextFunction) => { const result = schema.safeParse(req.body);

if (!result.success) {
  return res.status(400).json({
    code: 'VALIDATION_ERROR',
    errors: formatZodError(result.error),
  });
}

req.body = result.data;
next();

}; }

// Usage app.post('/users', validate(createUserSchema), createUser);

// tRPC integration export const appRouter = t.router({ createUser: t.procedure .input(createUserSchema) .mutation(({ input }) => { // input is fully typed and validated return db.users.create({ data: input }); }), });

Complex Validations

// Conditional fields const formSchema = z.discriminatedUnion('type', [ z.object({ type: z.literal('individual'), name: z.string(), ssn: z.string().regex(/^\d{3}-\d{2}-\d{4}$/), }), z.object({ type: z.literal('business'), companyName: z.string(), ein: z.string().regex(/^\d{2}-\d{7}$/), }), ]);

// Async validation const uniqueEmailSchema = z.string().email().refine( async (email) => { const exists = await db.users.findByEmail(email); return !exists; }, { message: 'Email already registered' } );

// Transform and validate const dateSchema = z.string() .transform((str) => new Date(str)) .refine((date) => !isNaN(date.getTime()), 'Invalid date');

// Preprocess for type coercion const querySchema = z.object({ page: z.preprocess( (val) => parseInt(val as string, 10), z.number().min(1).default(1) ), limit: z.preprocess( (val) => parseInt(val as string, 10), z.number().min(1).max(100).default(20) ), });

Testing

import { describe, it, expect } from 'vitest';

describe('userSchema', () => { it('validates correct input', () => { const input = { email: 'test@example.com', password: 'Password1!' }; const result = userSchema.safeParse(input);

expect(result.success).toBe(true);
if (result.success) {
  expect(result.data.email).toBe('test@example.com');
}

});

it('fails on invalid email', () => { const input = { email: 'invalid', password: 'Password1!' }; const result = userSchema.safeParse(input);

expect(result.success).toBe(false);
if (!result.success) {
  expect(result.error.flatten().fieldErrors.email).toContain('Invalid email format');
}

});

it('fails on weak password', () => { const input = { email: 'test@example.com', password: 'weak' }; const result = userSchema.safeParse(input);

expect(result.success).toBe(false);

}); });

// Property-based testing with fast-check import * as fc from 'fast-check';

it('accepts all valid emails', () => { fc.assert( fc.property(fc.emailAddress(), (email) => { const result = z.string().email().safeParse(email); return result.success; }) ); });

Performance

// Define schemas outside components/functions const schemas = { user: z.object({ /* ... / }), product: z.object({ / ... */ }), } as const;

// Lazy loading for circular references const categorySchema: z.ZodType<Category> = z.lazy(() => z.object({ name: z.string(), children: z.array(categorySchema).optional(), }) );

// Coercion for better performance on known types const numberSchema = z.coerce.number(); // Auto-converts strings const dateSchema = z.coerce.date();

Monitoring Metrics

Metric Target

Validation errors Track & analyze

Schema coverage 100% API inputs

Type inference All schemas

Parse time < 5ms

Checklist

  • Custom error messages

  • safeParse for user input

  • Error formatting for API

  • Schemas defined at module level

  • Type inference (z.infer)

  • Complex validation (refine)

  • Async validation where needed

  • Unit tests for schemas

  • Integration with React Hook Form

  • OpenAPI generation (zod-to-openapi)

Further Reading

For advanced validations: mcp__documentation__fetch_docs

  • Technology: zod (available in MCP)

  • Zod Docs

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

Planning with files

Implements Manus-style file-based planning to organize and track progress on complex tasks. Creates task_plan.md, findings.md, and progress.md. Use when aske...

Registry SourceRecently Updated
8.4K22Profile unavailable
Coding

cron-scheduling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

token-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-19

No summary provided by upstream source.

Repository SourceNeeds Review