<< All versions
Skill v1.0.1
currentAutomated scan100/100majiayu000/claude-skill-registry-data/zod-4-josecortezz25-voto-claro-colombia-2
3 files
──Details
PublishedMay 22, 2026 at 06:53 PM
Content Hashsha256:b3d65db3f37af8fa...
Git SHA5bd77048d9f5
Bump Typepatch
──Files
Files (1 file, 4.8 KB)
SKILL.md4.8 KBactive
SKILL.md · 221 lines · 4.8 KB
version: "1.0.1" name: zod-4 description: > Zod 4 schema validation patterns. Trigger: When using Zod for validation - breaking changes from v3. license: Apache-2.0 metadata: version: '1.0'
Breaking Changes from Zod 3
typescript
// ❌ Zod 3 (OLD)z.string().email();z.string().uuid();z.string().url();z.string().nonempty();z.object({ name: z.string() }).required_error('Required');// ✅ Zod 4 (NEW)z.email();z.uuid();z.url();z.string().min(1);z.object({ name: z.string() }, { error: 'Required' });
Basic Schemas
typescript
import { z } from 'zod';// Primitivesconst stringSchema = z.string();const numberSchema = z.number();const booleanSchema = z.boolean();const dateSchema = z.date();// Top-level validators (Zod 4)const emailSchema = z.email();const uuidSchema = z.uuid();const urlSchema = z.url();// With constraintsconst nameSchema = z.string().min(1).max(100);const ageSchema = z.number().int().positive().max(150);const priceSchema = z.number().min(0).multipleOf(0.01);
Object Schemas
typescript
const userSchema = z.object({id: z.uuid(),email: z.email({ error: 'Invalid email address' }),name: z.string().min(1, { error: 'Name is required' }),age: z.number().int().positive().optional(),role: z.enum(['admin', 'user', 'guest']),metadata: z.record(z.string(), z.unknown()).optional()});type User = z.infer<typeof userSchema>;// Parsingconst user = userSchema.parse(data); // Throws on errorconst result = userSchema.safeParse(data); // Returns { success, data/error }if (result.success) {console.log(result.data);} else {console.log(result.error.issues);}
Arrays and Records
typescript
// Arraysconst tagsSchema = z.array(z.string()).min(1).max(10);const numbersSchema = z.array(z.number()).nonempty();// Records (objects with dynamic keys)const scoresSchema = z.record(z.string(), z.number());// { [key: string]: number }// Tuplesconst coordinatesSchema = z.tuple([z.number(), z.number()]);// [number, number]
Unions and Discriminated Unions
typescript
// Simple unionconst stringOrNumber = z.union([z.string(), z.number()]);// Discriminated union (more efficient)const resultSchema = z.discriminatedUnion('status', [z.object({ status: z.literal('success'), data: z.unknown() }),z.object({ status: z.literal('error'), error: z.string() })]);
Transformations
typescript
// Transform during parsingconst lowercaseEmail = z.email().transform(email => email.toLowerCase());// Coercion (convert types)const numberFromString = z.coerce.number(); // "42" → 42const dateFromString = z.coerce.date(); // "2024-01-01" → Date// Preprocessingconst trimmedString = z.preprocess(val => (typeof val === 'string' ? val.trim() : val),z.string());
Refinements
typescript
const passwordSchema = z.string().min(8).refine(val => /[A-Z]/.test(val), {message: 'Must contain uppercase letter'}).refine(val => /[0-9]/.test(val), {message: 'Must contain number'});// With superRefine for multiple errorsconst formSchema = z.object({password: z.string(),confirmPassword: z.string()}).superRefine((data, ctx) => {if (data.password !== data.confirmPassword) {ctx.addIssue({code: z.ZodIssueCode.custom,message: "Passwords don't match",path: ['confirmPassword']});}});
Optional and Nullable
typescript
// Optional (T | undefined)z.string().optional();// Nullable (T | null)z.string().nullable();// Both (T | null | undefined)z.string().nullish();// Default valuesz.string().default('unknown');z.number().default(() => Math.random());
Error Handling
typescript
// Zod 4: Use 'error' param instead of 'message'const schema = z.object({name: z.string({ error: 'Name must be a string' }),email: z.email({ error: 'Invalid email format' }),age: z.number().min(18, { error: 'Must be 18 or older' })});// Custom error mapconst customSchema = z.string({error: issue => {if (issue.code === 'too_small') {return 'String is too short';}return 'Invalid string';}});
React Hook Form Integration
typescript
import { useForm } from "react-hook-form";import { zodResolver } from "@hookform/resolvers/zod";const schema = z.object({email: z.email(),password: z.string().min(8),});type FormData = z.infer<typeof schema>;function Form() {const { register, handleSubmit, formState: { errors } } = useForm<FormData>({resolver: zodResolver(schema),});return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("email")} />{errors.email && <span>{errors.email.message}</span>}</form>);}
Keywords
zod, validation, schema, typescript, forms, parsing