"Create complete Zod validation for checkout flow:1. Customer info: email, phone, billing address2. Shipping: address with validation (can't be PO box), preferred delivery date3. Payment: discriminated union for credit card, PayPal, crypto4. Items: array of products with quantity (min 1, max 10), size, color5. Promo code: optional, alphanumeric, validate against API6. Total must match cart calculation7. Accept terms and conditions (required)"
Skill Content (2)
Additional code example for this skill.
zod-schema-validator.txt
"Build API validation middleware with Zod:1. Validate request headers (auth token, content-type)2. Parse and validate query parameters with coercion3. Validate request body based on endpoint4. Add rate limiting metadata validation5. Validate response format before sending to client6. Log validation errors with request context7. Return standardized error responses"
Skill Content (3)
Additional code example for this skill.
zod-schema-validator.txt
"Create Zod schemas for database operations:1. User input sanitization before INSERT2. Strip dangerous characters from strings3. Validate foreign key relationships exist4. Ensure email uniqueness with async validator5. Transform dates to ISO format6. Validate JSON columns match expected structure7. Add database constraint validation"
Skill Content (4)
Additional code example for this skill.
zod-schema-validator.txt
"Build file upload validator with Zod:1. Validate MIME types (images: PNG, JPG, WebP)2. Check file size (max 5MB)3. Validate image dimensions (min 800x600, max 4000x4000)4. Sanitize filename (alphanumeric, hyphens, underscores)5. Validate metadata (EXIF data)6. Check for malware signatures7. Transform to standard format"
Features
Key capabilities and functionality
TypeScript-first with automatic type inference
Zero dependencies, 8kb minified
Composable schemas with .extend() and .merge()
Custom validation with .refine() and async support
Use Cases
Common scenarios and applications
API request/response validation
Form validation with error messages
Database input sanitization
Requirements
Prerequisites and dependencies
TypeScript 5.0+
zod ^3.22.0
Node.js 18+ or modern browser
Installation
Setup instructions and requirements
Claude Code Setup
Step 1: Run command
claude code setup-1.sh
bash
npminstallzod
Step 2: Run command
claude code setup-2.sh
bash
npminstall@hookform/resolvers(forReactHookForm)
Create schemas in src/schemas/
Import and use with safeParse() or parse()
Claude Desktop Setup
Install Zod: npm install zod
Ask Claude: 'Create Zod validation schemas for [your use case]'
Claude generates schemas with TypeScript types
Integrate with forms or API routes
Troubleshooting
Common issues and solutions
Type inference returns 'any'
Check TypeScript version is 5.0+. Ensure you're using 'z.infer<typeof schema>' correctly. Update tsconfig.json with strict: true.
Optional fields not working
Use .optional() for optional, .nullable() for null, .default() for defaults. Don't chain .optional().nullable() unless you need both undefined and null.
Async validation failing
Use .refine() with async callback, call .parseAsync() or .safeParseAsync(), ensure you await the result.
Usage Examples
Practical code examples demonstrating common use cases and implementation patterns
User Registration Schema
user-registration-schema.ts
typescript
import{z}from'zod';constpasswordSchema=z.string().min(8,'Password must be at least 8 characters').regex(/[0-9]/,'Password must contain a number').regex(/[^a-zA-Z0-9]/,'Password must contain a special character');constuserRegistrationSchema=z.object({email:z.string().email('Invalid email address'),password:passwordSchema,confirmPassword:z.string(),age:z.number().int().min(18,'Must be 18 or older').max(100),phone:z.string().regex(/^\+?[1-9]\d{1,14}$/).optional(),acceptTerms:z.literal(true,{errorMap:()=>({message:'You must accept the terms'}),}),}).refine((data)=>data.password===data.confirmPassword,{message:'Passwords do not match',path:['confirmPassword'],});typeUserRegistration=z.infer<typeofuserRegistrationSchema>;// Usageconst result = userRegistrationSchema.safeParse({email:'user@example.com',password:'SecureP@ss1',confirmPassword:'SecureP@ss1',age:25,acceptTerms:true,});if (!result.success) {console.error(result.error.format());} else {console.log('Valid user:',result.data);}
React Hook Form Integration
react-hook-form-integration.ts
typescript
import{useForm}from'react-hook-form';import{zodResolver}from'@hookform/resolvers/zod';import{z}from'zod';constformSchema=z.object({name:z.string().min(2,'Name must be at least 2 characters'),email:z.string().email(),address:z.object({street:z.string().min(5),city:z.string().min(2),state:z.string().length(2,'Use 2-letter state code'),zip:z.string().regex(/^\d{5}(-\d{4})?$/,'Invalid ZIP code'),}),});typeFormData=z.infer<typeofformSchema>;export function RegistrationForm() {const{register,handleSubmit,formState:{errors},} = useForm<FormData>({resolver:zodResolver(formSchema),}); const onSubmit = (data: FormData) =>{console.log('Valid form data:',data);}; return (<formonSubmit={handleSubmit(onSubmit)}><input{...register('name')}/>{errors.name&&<span>{errors.name.message}</span>}<input{...register('email')}/>{errors.email&&<span>{errors.email.message}</span>}<input{...register('address.street')}placeholder="Street"/>{errors.address?.street&&<span>{errors.address.street.message}</span>}{/* ... other fields ... */}<buttontype="submit">Submit</button></form>);}
API Validation Middleware
api-validation-middleware.ts
typescript
import{z}from'zod';import{Request,Response,NextFunction}from'express';constcreateUserSchema=z.object({body:z.object({name:z.string().min(2),email:z.string().email(),role:z.enum(['user','admin']).default('user'),}),query:z.object({sendWelcomeEmail:z.string().transform((val)=>val==='true').default('false'),}),});typeCreateUserRequest=z.infer<typeofcreateUserSchema>;export const validateRequest = (schema: z.ZodSchema) => async (req: Request, res: Response, next: NextFunction) =>{try{constresult=awaitschema.parseAsync({body:req.body,query:req.query,params:req.params,}); req.body = result.body; req.query = result.query as any; next();} catch (error) {if(errorinstanceofz.ZodError){res.status(400).json({error:'Validation failed',details:error.format(),});} else {next(error);}}};// Usageapp.post('/users', validateRequest(createUserSchema), async (req, res) =>{const{name,email,role} = req.body;// Data is validated and typed const user = await createUser({name,email,role}); res.json(user);});
Discriminated Union for Payments
discriminated-union-for-payments.ts
typescript
import{z}from'zod';constcreditCardPayment=z.object({method:z.literal('credit_card'),cardNumber:z.string().regex(/^\d{16}$/),expiryMonth:z.number().min(1).max(12),expiryYear:z.number().min(2025),cvv:z.string().regex(/^\d{3,4}$/),});constpaypalPayment=z.object({method:z.literal('paypal'),email:z.string().email(),});constcryptoPayment=z.object({method:z.literal('crypto'),walletAddress:z.string().regex(/^0x[a-fA-F0-9]{40}$/),cryptocurrency:z.enum(['BTC','ETH','USDC']),});constpaymentSchema=z.discriminatedUnion('method',[creditCardPayment,paypalPayment,cryptoPayment,]);typePayment=z.infer<typeofpaymentSchema>;// TypeScript knows the shape based on methodfunction processPayment(payment: Payment) {switch(payment.method){case'credit_card':returnchargeCreditCard(payment.cardNumber,payment.cvv);case'paypal':returnchargePayPal(payment.email);case'crypto':returnchargeCrypto(payment.walletAddress);}}