[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M78463GGSP9B3JSF146B2MG0":3,"skill-same:01M78463GGSP9B3JSF146B2MG0":151},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":88,"commitSha":89,"skillDirectory":90,"forksCount":13,"repositoryHtmlUrl":91,"repositoryHomepageUrl":6,"ownerHtmlUrl":92,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":93,"install":94,"resources":106},"01M78463GGSP9B3JSF146B2MG0","zod",null,"TypeScript-first schema validation and type inference. Use for validating API requests\u002Fresponses, form data, env vars, configs, defining type-safe schemas with runtime validation, transforming data, generating JSON Schema for OpenAPI\u002FAI, or encountering missing validation errors, type inference issues, validation error handling problems. Zero dependencies (2kb gzipped).","aibizmod\u002Faibizmod-service-web","aibizmod","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F295315630?v=4","01M7836CB8EQY701YQ7N88M591","01M7836CBVPZGNSJ8BRP2BT398",0,"MIT","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: zod\ndescription: TypeScript-first schema validation and type inference. Use for validating API requests\u002Fresponses, form data, env vars, configs, defining type-safe schemas with runtime validation, transforming data, generating JSON Schema for OpenAPI\u002FAI, or encountering missing validation errors, type inference issues, validation error handling problems. Zero dependencies (2kb gzipped).\nlicense: MIT\nmetadata:\n  version: 2.0.0\n  last_verified: 2025-11-17\n  package_version: 4.1.12+\n  keywords:\n    - zod\n    - validation\n    - schema\n    - typescript\n    - type-safety\n    - runtime-validation\n    - type-inference\n    - data-validation\n    - form-validation\n    - api-validation\n    - json-schema\n    - refinement\n    - transformation\n    - error-handling\n    - parse\n    - safeParse\n    - z.object\n    - z.string\n    - z.number\n    - z.array\n    - z.union\n    - z.discriminatedUnion\n    - z.refine\n    - z.transform\n    - z.infer\n    - z.coerce\n    - z.enum\n    - z.literal\n    - z.tuple\n    - z.record\n    - z.intersection\n    - z.codec\n    - z.toJSONSchema\n    - z.treeifyError\n    - z.flattenError\n    - z.prettifyError\n    - z.registry\n    - z.globalRegistry\n    - .register\n    - .meta\n    - error-customization\n    - localization\n    - i18n\n    - migration\n    - v3-to-v4\n    - breaking-changes\n    - tRPC\n    - prisma-zod\n    - react-hook-form\n    - trpc\n    - environment-variables\n    - env-validation\n    - config-validation\n    - dto\n    - type-guard\n    - runtime-type-checking\n  token_savings: 65%\n  errors_prevented: 8\n  production_tested: true\n  related_skills:\n    - react-hook-form-zod\n---\n\n# Zod: TypeScript-First Schema Validation\n\n## Overview\n\nZod is a TypeScript-first validation library that enables developers to define schemas for validating data at runtime while automatically inferring static TypeScript types. With zero dependencies and a 2kb core bundle (gzipped), Zod provides immutable, composable validation with comprehensive error handling.\n\n## Installation\n\n```bash\nbun add zod\n# or\nbun add zod\n# or\nbun add zod\n# or\nyarn add zod\n```\n\n**Requirements**:\n- TypeScript v5.5+ with `\"strict\": true` in `tsconfig.json`\n- Zod 4.x (4.1.12+)\n\n**Important**: This skill documents **Zod 4.x** features. The following APIs require Zod 4 and are NOT available in Zod 3.x:\n- `z.codec()` - Bidirectional transformations\n- `z.iso.date()`, `z.iso.time()`, `z.iso.datetime()`, `z.iso.duration()` - ISO format validators\n- `z.toJSONSchema()` - JSON Schema generation\n- `z.treeifyError()`, `z.prettifyError()`, `z.flattenError()` - New error formatting helpers\n- `.meta()` - Enhanced metadata (Zod 3.x only has `.describe()`)\n- Unified `error` parameter - Replaces `message`, `invalid_type_error`, `required_error`, `errorMap`\n\nFor Zod 3.x compatibility or migration guidance, see https:\u002F\u002Fzod.dev\n\n## Migrating from Zod v3 to v4\n\n**Load `references\u002Fmigration-guide.md` for complete v3 to v4 migration documentation.**\n\n### Quick Summary\n\nZod v4 introduces breaking changes for better performance:\n\n- **Error customization**: Use unified `error` parameter (replaces `message`, `invalid_type_error`, `required_error`)\n- **Number validation**: Stricter - rejects `Infinity` and unsafe integers\n- **String formats**: Now top-level functions (`z.email()` vs `z.string().email()`)\n- **Object defaults**: Applied even in optional fields\n- **Deprecated APIs**: Use `.extend()` (not `.merge()`), `z.treeifyError()` (not `error.format()`)\n- **Function validation**: Use `.implement()` method\n- **UUID validation**: Stricter RFC 9562\u002F4122 compliance\n\n**→ Load `references\u002Fmigration-guide.md` for:** Complete breaking changes, migration checklist, gradual migration strategy, rollback instructions\n\n## Core Concepts\n\n### Basic Usage Pattern\n\n```typescript\nimport { z } from \"zod\";\n\n\u002F\u002F Define schema\nconst UserSchema = z.object({\n  username: z.string(),\n  age: z.number().int().positive(),\n  email: z.string().email(),\n});\n\n\u002F\u002F Infer TypeScript type\ntype User = z.infer\u003Ctypeof UserSchema>;\n\n\u002F\u002F Validate data (throws on error)\nconst user = UserSchema.parse(data);\n\n\u002F\u002F Validate data (returns result object)\nconst result = UserSchema.safeParse(data);\nif (result.success) {\n  console.log(result.data); \u002F\u002F Typed!\n} else {\n  console.error(result.error); \u002F\u002F ZodError\n}\n```\n\n### Parsing Methods\n\nUse the appropriate parsing method based on error handling needs:\n\n- **`.parse(data)`** - Throws `ZodError` on invalid input; returns strongly-typed data on success\n- **`.safeParse(data)`** - Returns `{ success: true, data }` or `{ success: false, error }` (no exceptions)\n- **`.parseAsync(data)`** - For schemas with async refinements\u002Ftransforms\n- **`.safeParseAsync(data)`** - Async version that doesn't throw\n\n**Best Practice**: Use `.safeParse()` to avoid try-catch blocks and leverage discriminated unions.\n\n## Primitive Types\n\n### Strings\n\n```typescript\nz.string()                    \u002F\u002F Basic string\nz.string().min(5)            \u002F\u002F Minimum length\nz.string().max(100)          \u002F\u002F Maximum length\nz.string().length(10)        \u002F\u002F Exact length\nz.string().email()           \u002F\u002F Email validation\nz.string().url()             \u002F\u002F URL validation\nz.string().uuid()            \u002F\u002F UUID format\nz.string().regex(\u002F^\\d+$\u002F)    \u002F\u002F Custom pattern\nz.string().startsWith(\"pre\") \u002F\u002F Prefix check\nz.string().endsWith(\"suf\")   \u002F\u002F Suffix check\nz.string().trim()            \u002F\u002F Auto-trim whitespace\nz.string().toLowerCase()     \u002F\u002F Auto-lowercase\nz.string().toUpperCase()     \u002F\u002F Auto-uppercase\n\n\u002F\u002F ISO formats (Zod 4+)\nz.iso.date()                 \u002F\u002F YYYY-MM-DD\nz.iso.time()                 \u002F\u002F HH:MM:SS\nz.iso.datetime()             \u002F\u002F ISO 8601 datetime\nz.iso.duration()             \u002F\u002F ISO 8601 duration\n\n\u002F\u002F Network formats\nz.ipv4()                     \u002F\u002F IPv4 address\nz.ipv6()                     \u002F\u002F IPv6 address\nz.cidrv4()                   \u002F\u002F IPv4 CIDR notation\nz.cidrv6()                   \u002F\u002F IPv6 CIDR notation\n\n\u002F\u002F Other formats\nz.jwt()                      \u002F\u002F JWT token\nz.nanoid()                   \u002F\u002F Nanoid\nz.cuid()                     \u002F\u002F CUID\nz.cuid2()                    \u002F\u002F CUID2\nz.ulid()                     \u002F\u002F ULID\nz.base64()                   \u002F\u002F Base64 encoded\nz.hex()                      \u002F\u002F Hexadecimal\n```\n\n### Numbers\n\n```typescript\nz.number()                   \u002F\u002F Basic number\nz.number().int()             \u002F\u002F Integer only\nz.number().positive()        \u002F\u002F > 0\nz.number().nonnegative()     \u002F\u002F >= 0\nz.number().negative()        \u002F\u002F \u003C 0\nz.number().nonpositive()     \u002F\u002F \u003C= 0\nz.number().min(0)            \u002F\u002F Minimum value\nz.number().max(100)          \u002F\u002F Maximum value\nz.number().gt(0)             \u002F\u002F Greater than\nz.number().gte(0)            \u002F\u002F Greater than or equal\nz.number().lt(100)           \u002F\u002F Less than\nz.number().lte(100)          \u002F\u002F Less than or equal\nz.number().multipleOf(5)     \u002F\u002F Must be multiple of 5\nz.int()                      \u002F\u002F Shorthand for z.number().int()\nz.int32()                    \u002F\u002F 32-bit integer\nz.nan()                      \u002F\u002F NaN value\n```\n\n### Coercion (Type Conversion)\n\n```typescript\nz.coerce.string()            \u002F\u002F Convert to string\nz.coerce.number()            \u002F\u002F Convert to number\nz.coerce.boolean()           \u002F\u002F Convert to boolean\nz.coerce.bigint()            \u002F\u002F Convert to bigint\nz.coerce.date()              \u002F\u002F Convert to Date\n\n\u002F\u002F Example: Parse query parameters\nconst QuerySchema = z.object({\n  page: z.coerce.number().int().positive(),\n  limit: z.coerce.number().int().max(100).default(10),\n});\n\n\u002F\u002F \"?page=5&limit=20\" -> { page: 5, limit: 20 }\n```\n\n### Other Primitives\n\n```typescript\nz.boolean()                  \u002F\u002F Boolean\nz.date()                     \u002F\u002F Date object\nz.date().min(new Date(\"2020-01-01\"))\nz.date().max(new Date(\"2030-12-31\"))\nz.bigint()                   \u002F\u002F BigInt\nz.symbol()                   \u002F\u002F Symbol\nz.null()                     \u002F\u002F Null\nz.undefined()                \u002F\u002F Undefined\nz.void()                     \u002F\u002F Void (undefined)\n```\n\n## Complex Types\n\n### Objects\n\n```typescript\nconst PersonSchema = z.object({\n  name: z.string(),\n  age: z.number(),\n  address: z.object({\n    street: z.string(),\n    city: z.string(),\n    country: z.string(),\n  }),\n});\n\ntype Person = z.infer\u003Ctypeof PersonSchema>;\n\n\u002F\u002F Object methods\nPersonSchema.shape                 \u002F\u002F Access shape\nPersonSchema.keyof()              \u002F\u002F Get union of keys\nPersonSchema.extend({ role: z.string() })  \u002F\u002F Add fields\nPersonSchema.pick({ name: true }) \u002F\u002F Pick specific fields\nPersonSchema.omit({ age: true })  \u002F\u002F Omit fields\nPersonSchema.partial()            \u002F\u002F Make all fields optional\nPersonSchema.required()           \u002F\u002F Make all fields required\nPersonSchema.deepPartial()        \u002F\u002F Recursively optional\n\n\u002F\u002F Strict vs loose objects\nz.strictObject({ ... })           \u002F\u002F No extra keys allowed (throws)\nz.object({ ... })                 \u002F\u002F Strips extra keys (default)\nz.looseObject({ ... })            \u002F\u002F Allows extra keys\n```\n\n### Arrays\n\n```typescript\nz.array(z.string())              \u002F\u002F String array\nz.array(z.number()).min(1)       \u002F\u002F At least 1 element\nz.array(z.number()).max(10)      \u002F\u002F At most 10 elements\nz.array(z.number()).length(5)    \u002F\u002F Exactly 5 elements\nz.array(z.number()).nonempty()   \u002F\u002F At least 1 element\n\n\u002F\u002F Nested arrays\nz.array(z.array(z.number()))     \u002F\u002F number[][]\n```\n\n### Tuples\n\n```typescript\nz.tuple([z.string(), z.number()]) \u002F\u002F [string, number]\nz.tuple([z.string(), z.number()]).rest(z.boolean()) \u002F\u002F [string, number, ...boolean[]]\n```\n\n### Enums and Literals\n\n```typescript\n\u002F\u002F Enum\nconst RoleEnum = z.enum([\"admin\", \"user\", \"guest\"]);\ntype Role = z.infer\u003Ctypeof RoleEnum>; \u002F\u002F \"admin\" | \"user\" | \"guest\"\n\n\u002F\u002F Literal values\nz.literal(\"exact_value\")\nz.literal(42)\nz.literal(true)\n\n\u002F\u002F Native TypeScript enum\nenum Fruits {\n  Apple,\n  Banana,\n}\nz.nativeEnum(Fruits)\n\n\u002F\u002F Enum methods\nRoleEnum.enum.admin              \u002F\u002F \"admin\"\nRoleEnum.exclude([\"guest\"])      \u002F\u002F Exclude values\nRoleEnum.extract([\"admin\", \"user\"]) \u002F\u002F Include only\n```\n\n### Unions\n\n```typescript\n\u002F\u002F Basic union\nz.union([z.string(), z.number()])\n\n\u002F\u002F Discriminated union (better performance & type inference)\nconst ResponseSchema = z.discriminatedUnion(\"status\", [\n  z.object({ status: z.literal(\"success\"), data: z.any() }),\n  z.object({ status: z.literal(\"error\"), message: z.string() }),\n]);\n\ntype Response = z.infer\u003Ctypeof ResponseSchema>;\n\u002F\u002F { status: \"success\", data: any } | { status: \"error\", message: string }\n```\n\n### Intersections\n\n```typescript\nconst BaseSchema = z.object({ id: z.string() });\nconst ExtendedSchema = z.object({ name: z.string() });\n\nconst Combined = z.intersection(BaseSchema, ExtendedSchema);\n\u002F\u002F Equivalent to: z.object({ id: z.string(), name: z.string() })\n```\n\n### Records and Maps\n\n```typescript\n\u002F\u002F Record: object with typed keys and values\nz.record(z.string())             \u002F\u002F { [key: string]: string }\nz.record(z.string(), z.number()) \u002F\u002F { [key: string]: number }\n\n\u002F\u002F Partial record (some keys optional)\nz.partialRecord(z.enum([\"a\", \"b\"]), z.string())\n\n\u002F\u002F Map\nz.map(z.string(), z.number())    \u002F\u002F Map\u003Cstring, number>\nz.set(z.string())                \u002F\u002F Set\u003Cstring>\n```\n\n## Advanced Patterns\n\n**Load `references\u002Fadvanced-patterns.md` for complete advanced validation and transformation patterns.**\n\n### Quick Reference\n\n**Refinements** (custom validation):\n```typescript\nz.string().refine((val) => val.length >= 8, \"Too short\");\nz.object({ password, confirmPassword }).superRefine((data, ctx) => { \u002F* ... *\u002F });\n```\n\n**Transformations** (modify data):\n```typescript\nz.string().transform((val) => val.trim());\nz.string().pipe(z.coerce.number());\n```\n\n**Codecs** (bidirectional transforms - NEW in v4.1):\n```typescript\nconst DateCodec = z.codec(\n  z.iso.datetime(),\n  z.date(),\n  {\n    decode: (str) => new Date(str),\n    encode: (date) => date.toISOString(),\n  }\n);\n```\n\n**Recursive Types**:\n```typescript\nconst CategorySchema: z.ZodType\u003CCategory> = z.lazy(() =>\n  z.object({ name: z.string(), subcategories: z.array(CategorySchema) })\n);\n```\n\n**Optional\u002FNullable**:\n```typescript\nz.string().optional()            \u002F\u002F string | undefined\nz.string().nullable()            \u002F\u002F string | null\nz.string().default(\"default\")    \u002F\u002F Provides default if undefined\n```\n\n**Readonly & Brand**:\n```typescript\nz.object({ ... }).readonly()     \u002F\u002F Readonly properties\nz.string().brand\u003C\"UserId\">()     \u002F\u002F Nominal typing\n```\n\n**→ Load `references\u002Fadvanced-patterns.md` for:** Complete refinement patterns, async validation, codec examples, composable schemas, conditional validation, performance optimization\n\n## Error Handling\n\n**Load `references\u002Ferror-handling.md` for complete error formatting and customization guide.**\n\n### Quick Reference\n\n**Error Formatting Methods**:\n```typescript\n\u002F\u002F For forms\nconst { fieldErrors } = z.flattenError(error);\n\n\u002F\u002F For nested data\nconst tree = z.treeifyError(error);\nconst nameError = tree.properties?.user?.properties?.name?.errors?.[0];\n\n\u002F\u002F For debugging\nconsole.log(z.prettifyError(error));\n```\n\n**Custom Error Messages** (three levels):\n```typescript\n\u002F\u002F 1. Schema-level (highest priority)\nz.string({ error: \"Custom message\" });\nz.string().min(5, \"Too short\");\n\n\u002F\u002F 2. Per-parse level\nschema.parse(data, { error: (issue) => ({ message: \"...\" }) });\n\n\u002F\u002F 3. Global level\nz.config({ customError: (issue) => ({ message: \"...\" }) });\n```\n\n**Localization** (40+ languages):\n```typescript\nz.config(z.locales.es());  \u002F\u002F Spanish\nz.config(z.locales.fr());  \u002F\u002F French\n```\n\n**→ Load `references\u002Ferror-handling.md` for:** Complete error formatting examples, custom error patterns, localization setup, error code reference\n\n## Type Inference\n\n**Load `references\u002Ftype-inference.md` for complete type inference and metadata documentation.**\n\n### Quick Reference\n\n**Basic Type Inference**:\n```typescript\nconst UserSchema = z.object({ name: z.string() });\ntype User = z.infer\u003Ctypeof UserSchema>; \u002F\u002F { name: string }\n```\n\n**Input vs Output** (for transforms):\n```typescript\nconst TransformSchema = z.string().transform((s) => s.length);\ntype Input = z.input\u003Ctypeof TransformSchema>;   \u002F\u002F string\ntype Output = z.output\u003Ctypeof TransformSchema>; \u002F\u002F number\n```\n\n**JSON Schema Conversion**:\n```typescript\nconst jsonSchema = z.toJSONSchema(UserSchema, {\n  target: \"openapi-3.0\",\n  metadata: true,\n});\n```\n\n**Metadata**:\n```typescript\n\u002F\u002F Add metadata\nconst EmailSchema = z.string().email().meta({\n  title: \"Email Address\",\n  description: \"User's email address\",\n});\n\n\u002F\u002F Create custom registry\nconst formRegistry = z.registry\u003CFormFieldMeta>();\n```\n\n**→ Load `references\u002Ftype-inference.md` for:** Complete type inference patterns, JSON Schema options, metadata system, custom registries, brand types\n\n## Functions\n\nValidate function inputs and outputs:\n\n```typescript\nconst AddFunction = z.function()\n  .args(z.number(), z.number())  \u002F\u002F Arguments\n  .returns(z.number());           \u002F\u002F Return type\n\n\u002F\u002F Implement typed function\nconst add = AddFunction.implement((a, b) => {\n  return a + b; \u002F\u002F Type-checked!\n});\n\n\u002F\u002F Async functions\nconst FetchFunction = z.function()\n  .args(z.string())\n  .returns(z.promise(z.object({ data: z.any() })))\n  .implementAsync(async (url) => {\n    const response = await fetch(url);\n    return response.json();\n  });\n```\n\n## Common Patterns\n\n### Environment Variables\n\n```typescript\nconst EnvSchema = z.object({\n  NODE_ENV: z.enum([\"development\", \"production\", \"test\"]),\n  DATABASE_URL: z.string().url(),\n  PORT: z.coerce.number().int().positive().default(3000),\n  API_KEY: z.string().min(32),\n});\n\n\u002F\u002F Validate on startup\nconst env = EnvSchema.parse(process.env);\n\n\u002F\u002F Now use typed env\nconsole.log(env.PORT); \u002F\u002F number\n```\n\n### API Request Validation\n\n```typescript\nconst CreateUserRequest = z.object({\n  username: z.string().min(3).max(20),\n  email: z.string().email(),\n  password: z.string().min(8),\n  age: z.number().int().positive().optional(),\n});\n\n\u002F\u002F Express example\napp.post(\"\u002Fusers\", async (req, res) => {\n  const result = CreateUserRequest.safeParse(req.body);\n\n  if (!result.success) {\n    return res.status(400).json({\n      errors: z.flattenError(result.error).fieldErrors,\n    });\n  }\n\n  const user = await createUser(result.data);\n  res.json(user);\n});\n```\n\n### Form Validation\n\n```typescript\nconst FormSchema = z.object({\n  firstName: z.string().min(1, \"First name required\"),\n  lastName: z.string().min(1, \"Last name required\"),\n  email: z.string().email(\"Invalid email\"),\n  age: z.coerce.number().int().min(18, \"Must be 18+\"),\n  agreeToTerms: z.literal(true, {\n    errorMap: () => ({ message: \"Must accept terms\" }),\n  }),\n});\n\ntype FormData = z.infer\u003Ctypeof FormSchema>;\n```\n\n### Partial Updates\n\n```typescript\nconst UserSchema = z.object({\n  id: z.string(),\n  name: z.string(),\n  email: z.string().email(),\n});\n\n\u002F\u002F For PATCH requests: make everything optional except id\nconst UpdateUserSchema = UserSchema.partial().required({ id: true });\n\ntype UpdateUser = z.infer\u003Ctypeof UpdateUserSchema>;\n\u002F\u002F { id: string; name?: string; email?: string }\n```\n\n### Composable Schemas\n\n```typescript\n\u002F\u002F Base schemas\nconst TimestampSchema = z.object({\n  createdAt: z.date(),\n  updatedAt: z.date(),\n});\n\nconst AuthorSchema = z.object({\n  authorId: z.string(),\n  authorName: z.string(),\n});\n\n\u002F\u002F Compose into larger schemas\nconst PostSchema = z.object({\n  id: z.string(),\n  title: z.string(),\n  content: z.string(),\n}).merge(TimestampSchema).merge(AuthorSchema);\n```\n\n## Ecosystem Integration\n\n**Load `references\u002Fecosystem-integrations.md` for complete framework and tooling integration guide.**\n\n### Quick Reference\n\n**ESLint Plugins**:\n- `eslint-plugin-zod-x` - Enforces best practices\n- `eslint-plugin-import-zod` - Enforces import style\n\n**Framework Integrations**:\n- **tRPC** - End-to-end typesafe APIs\n- **React Hook Form** - Form validation (see `react-hook-form-zod` skill)\n- **Prisma** - Generate Zod from database models\n- **NestJS** - DTOs and validation pipes\n\n**Code Generation**:\n- **orval** - OpenAPI → Zod\n- **Hey API** - OpenAPI to TypeScript + Zod\n- **kubb** - API toolkit with codegen\n\n**→ Load `references\u002Fecosystem-integrations.md` for:** Setup instructions, integration examples, Hono middleware, Drizzle ORM patterns\n\n## Troubleshooting\n\n**Load `references\u002Ftroubleshooting.md` for complete troubleshooting guide, performance tips, and best practices.**\n\n### Quick Reference\n\n**Common Issues**:\n1. TypeScript strict mode required → Enable in `tsconfig.json`\n2. Large bundle size → Use `z.lazy()` for code splitting\n3. Slow async refinements → Cache or debounce\n4. Circular dependencies → Use `z.lazy()`\n5. Slow unions → Use `z.discriminatedUnion()`\n6. Transform vs refine confusion → Use `.refine()` for validation, `.transform()` for modification\n\n**Performance Tips**:\n- Use `.discriminatedUnion()` (5-10x faster than `.union()`)\n- Cache schema instances\n- Use `.safeParse()` (avoids try-catch overhead)\n- Lazy load large schemas\n\n**Best Practices**:\n- Define schemas at module level\n- Use type inference (`z.infer`)\n- Add custom error messages\n- Validate at system boundaries\n- Compose small schemas\n- Document with `.meta()`\n\n**→ Load `references\u002Ftroubleshooting.md` for:** Detailed solutions, performance optimization, best practices, testing patterns\n\n## Quick Reference\n\n```typescript\n\u002F\u002F Primitives\nz.string(), z.number(), z.boolean(), z.date(), z.bigint()\n\n\u002F\u002F Collections\nz.array(), z.tuple(), z.object(), z.record(), z.map(), z.set()\n\n\u002F\u002F Special types\nz.enum(), z.union(), z.discriminatedUnion(), z.intersection()\nz.literal(), z.any(), z.unknown(), z.never()\n\n\u002F\u002F Modifiers\n.optional(), .nullable(), .nullish(), .default(), .catch()\n.readonly(), .brand()\n\n\u002F\u002F Validation\n.min(), .max(), .length(), .regex(), .email(), .url(), .uuid()\n.refine(), .superRefine()\n\n\u002F\u002F Transformation\n.transform(), .pipe(), .codec()\n\n\u002F\u002F Parsing\n.parse(), .safeParse(), .parseAsync(), .safeParseAsync()\n\n\u002F\u002F Type inference\nz.infer\u003Ctypeof Schema>, z.input\u003Ctypeof Schema>, z.output\u003Ctypeof Schema>\n\n\u002F\u002F Error handling\nz.flattenError(), z.treeifyError(), z.prettifyError()\n\n\u002F\u002F JSON Schema\nz.toJSONSchema(schema, options)\n\n\u002F\u002F Metadata\n.meta(), .describe()\n\n\u002F\u002F Object methods\n.extend(), .pick(), .omit(), .partial(), .required(), .merge()\n```\n\n## When to Load References\n\n**Load `references\u002Fmigration-guide.md` when:**\n- Upgrading from Zod v3 to v4\n- Questions about breaking changes\n- Need migration checklist or rollback strategy\n- Errors related to deprecated APIs (`.merge()`, `error.format()`, etc.)\n- Number validation issues with `Infinity` or unsafe integers\n\n**Load `references\u002Ferror-handling.md` when:**\n- Need to format errors for forms or UI\n- Implementing custom error messages\n- Questions about `z.flattenError()`, `z.treeifyError()`, or `z.prettifyError()`\n- Setting up localization for error messages\n- Need error code reference or pattern examples\n\n**Load `references\u002Fadvanced-patterns.md` when:**\n- Implementing custom refinements or async validation\n- Need bidirectional transformations (codecs)\n- Working with recursive types or self-referential data\n- Questions about `.refine()`, `.transform()`, or `.codec()`\n- Need performance optimization patterns\n- Implementing conditional validation\n\n**Load `references\u002Ftype-inference.md` when:**\n- Questions about TypeScript type inference\n- Need to generate JSON Schema for OpenAPI or AI\n- Implementing metadata system for forms or documentation\n- Need custom registries for type-safe metadata\n- Questions about `z.infer`, `z.input`, `z.output`\n- Using brand types for ID safety\n\n**Load `references\u002Fecosystem-integrations.md` when:**\n- Integrating with tRPC, React Hook Form, Prisma, or NestJS\n- Setting up ESLint plugins for best practices\n- Generating Zod schemas from OpenAPI (orval, Hey API, kubb)\n- Questions about Hono middleware or Drizzle ORM\n- Need framework-specific integration examples\n\n**Load `references\u002Ftroubleshooting.md` when:**\n- Encountering TypeScript strict mode errors\n- Bundle size concerns or lazy loading needs\n- Performance issues with large unions or async refinements\n- Questions about circular dependencies\n- Need best practices or testing patterns\n- Confusion between `.refine()` and `.transform()`\n\n## Additional Resources\n\n- **Official Docs**: https:\u002F\u002Fzod.dev\n- **GitHub**: https:\u002F\u002Fgithub.com\u002Fcolinhacks\u002Fzod\n- **TypeScript Playground**: https:\u002F\u002Fzod-playground.vercel.app\n- **ESLint Plugin (Best Practices)**: https:\u002F\u002Fgithub.com\u002FJoshuaKGoldberg\u002Feslint-plugin-zod-x\n- **tRPC Integration**: https:\u002F\u002Ftrpc.io\n- **Ecosystem**: https:\u002F\u002Fzod.dev\u002Fecosystem\n\n---\n\n**Production Notes**:\n- Package version: 4.1.12+ (Zod 4.x stable)\n- Zero dependencies\n- Bundle size: 2kb (gzipped)\n- TypeScript 5.5+ required\n- Strict mode required\n- Last verified: 2025-11-17\n- Skill version: 2.0.0 (Updated with v4.1 enhancements)\n\n**What's New in This Version**:\n- ✨ Comprehensive v3 to v4 migration guide with breaking changes\n- ✨ Enhanced error customization with three-level system\n- ✨ Expanded metadata API with registry system\n- ✨ Improved error formatting with practical examples\n- ✨ Built-in localization support for 40+ locales\n- ✨ Detailed codec documentation with real-world patterns\n- ✨ Performance improvements and architectural changes explained\n","# Zod: TypeScript-First Schema Validation\n\n## Overview\n\nZod is a TypeScript-first validation library that enables developers to define schemas for validating data at runtime while automatically inferring static TypeScript types. With zero dependencies and a 2kb core bundle (gzipped), Zod provides immutable, composable validation with comprehensive error handling.\n\n## Installation\n\n```bash\nbun add zod\n# or\nbun add zod\n# or\nbun add zod\n# or\nyarn add zod\n```\n\n**Requirements**:\n- TypeScript v5.5+ with `\"strict\": true` in `tsconfig.json`\n- Zod 4.x (4.1.12+)\n\n**Important**: This skill documents **Zod 4.x** features. The following APIs require Zod 4 and are NOT available in Zod 3.x:\n- `z.codec()` - Bidirectional transformations\n- `z.iso.date()`, `z.iso.time()`, `z.iso.datetime()`, `z.iso.duration()` - ISO format validators\n- `z.toJSONSchema()` - JSON Schema generation\n- `z.treeifyError()`, `z.prettifyError()`, `z.flattenError()` - New error formatting helpers\n- `.meta()` - Enhanced metadata (Zod 3.x only has `.describe()`)\n- Unified `error` parameter - Replaces `message`, `invalid_type_error`, `required_error`, `errorMap`\n\nFor Zod 3.x compatibility or migration guidance, see https:\u002F\u002Fzod.dev\n\n## Migrating from Zod v3 to v4\n\n**Load `references\u002Fmigration-guide.md` for complete v3 to v4 migration documentation.**\n\n### Quick Summary\n\nZod v4 introduces breaking changes for better performance:\n\n- **Error customization**: Use unified `error` parameter (replaces `message`, `invalid_type_error`, `required_error`)\n- **Number validation**: Stricter - rejects `Infinity` and unsafe integers\n- **String formats**: Now top-level functions (`z.email()` vs `z.string().email()`)\n- **Object defaults**: Applied even in optional fields\n- **Deprecated APIs**: Use `.extend()` (not `.merge()`), `z.treeifyError()` (not `error.format()`)\n- **Function validation**: Use `.implement()` method\n- **UUID validation**: Stricter RFC 9562\u002F4122 compliance\n\n**→ Load `references\u002Fmigration-guide.md` for:** Complete breaking changes, migration checklist, gradual migration strategy, rollback instructions\n\n## Core Concepts\n\n### Basic Usage Pattern\n\n```typescript\nimport { z } from \"zod\";\n\n\u002F\u002F Define schema\nconst UserSchema = z.object({\n  username: z.string(),\n  age: z.number().int().positive(),\n  email: z.string().email(),\n});\n\n\u002F\u002F Infer TypeScript type\ntype User = z.infer\u003Ctypeof UserSchema>;\n\n\u002F\u002F Validate data (throws on error)\nconst user = UserSchema.parse(data);\n\n\u002F\u002F Validate data (returns result object)\nconst result = UserSchema.safeParse(data);\nif (result.success) {\n  console.log(result.data); \u002F\u002F Typed!\n} else {\n  console.error(result.error); \u002F\u002F ZodError\n}\n```\n\n### Parsing Methods\n\nUse the appropriate parsing method based on error handling needs:\n\n- **`.parse(data)`** - Throws `ZodError` on invalid input; returns strongly-typed data on success\n- **`.safeParse(data)`** - Returns `{ success: true, data }` or `{ success: false, error }` (no exceptions)\n- **`.parseAsync(data)`** - For schemas with async refinements\u002Ftransforms\n- **`.safeParseAsync(data)`** - Async version that doesn't throw\n\n**Best Practice**: Use `.safeParse()` to avoid try-catch blocks and leverage discriminated unions.\n\n## Primitive Types\n\n### Strings\n\n```typescript\nz.string()                    \u002F\u002F Basic string\nz.string().min(5)            \u002F\u002F Minimum length\nz.string().max(100)          \u002F\u002F Maximum length\nz.string().length(10)        \u002F\u002F Exact length\nz.string().email()           \u002F\u002F Email validation\nz.string().url()             \u002F\u002F URL validation\nz.string().uuid()            \u002F\u002F UUID format\nz.string().regex(\u002F^\\d+$\u002F)    \u002F\u002F Custom pattern\nz.string().startsWith(\"pre\") \u002F\u002F Prefix check\nz.string().endsWith(\"suf\")   \u002F\u002F Suffix check\nz.string().trim()            \u002F\u002F Auto-trim whitespace\nz.string().toLowerCase()     \u002F\u002F Auto-lowercase\nz.string().toUpperCase()     \u002F\u002F Auto-uppercase\n\n\u002F\u002F ISO formats (Zod 4+)\nz.iso.date()                 \u002F\u002F YYYY-MM-DD\nz.iso.time()                 \u002F\u002F HH:MM:SS\nz.iso.datetime()             \u002F\u002F ISO 8601 datetime\nz.iso.duration()             \u002F\u002F ISO 8601 duration\n\n\u002F\u002F Network formats\nz.ipv4()                     \u002F\u002F IPv4 address\nz.ipv6()                     \u002F\u002F IPv6 address\nz.cidrv4()                   \u002F\u002F IPv4 CIDR notation\nz.cidrv6()                   \u002F\u002F IPv6 CIDR notation\n\n\u002F\u002F Other formats\nz.jwt()                      \u002F\u002F JWT token\nz.nanoid()                   \u002F\u002F Nanoid\nz.cuid()                     \u002F\u002F CUID\nz.cuid2()                    \u002F\u002F CUID2\nz.ulid()                     \u002F\u002F ULID\nz.base64()                   \u002F\u002F Base64 encoded\nz.hex()                      \u002F\u002F Hexadecimal\n```\n\n### Numbers\n\n```typescript\nz.number()                   \u002F\u002F Basic number\nz.number().int()             \u002F\u002F Integer only\nz.number().positive()        \u002F\u002F > 0\nz.number().nonnegative()     \u002F\u002F >= 0\nz.number().negative()        \u002F\u002F \u003C 0\nz.number().nonpositive()     \u002F\u002F \u003C= 0\nz.number().min(0)            \u002F\u002F Minimum value\nz.number().max(100)          \u002F\u002F Maximum value\nz.number().gt(0)             \u002F\u002F Greater than\nz.number().gte(0)            \u002F\u002F Greater than or equal\nz.number().lt(100)           \u002F\u002F Less than\nz.number().lte(100)          \u002F\u002F Less than or equal\nz.number().multipleOf(5)     \u002F\u002F Must be multiple of 5\nz.int()                      \u002F\u002F Shorthand for z.number().int()\nz.int32()                    \u002F\u002F 32-bit integer\nz.nan()                      \u002F\u002F NaN value\n```\n\n### Coercion (Type Conversion)\n\n```typescript\nz.coerce.string()            \u002F\u002F Convert to string\nz.coerce.number()            \u002F\u002F Convert to number\nz.coerce.boolean()           \u002F\u002F Convert to boolean\nz.coerce.bigint()            \u002F\u002F Convert to bigint\nz.coerce.date()              \u002F\u002F Convert to Date\n\n\u002F\u002F Example: Parse query parameters\nconst QuerySchema = z.object({\n  page: z.coerce.number().int().positive(),\n  limit: z.coerce.number().int().max(100).default(10),\n});\n\n\u002F\u002F \"?page=5&limit=20\" -> { page: 5, limit: 20 }\n```\n\n### Other Primitives\n\n```typescript\nz.boolean()                  \u002F\u002F Boolean\nz.date()                     \u002F\u002F Date object\nz.date().min(new Date(\"2020-01-01\"))\nz.date().max(new Date(\"2030-12-31\"))\nz.bigint()                   \u002F\u002F BigInt\nz.symbol()                   \u002F\u002F Symbol\nz.null()                     \u002F\u002F Null\nz.undefined()                \u002F\u002F Undefined\nz.void()                     \u002F\u002F Void (undefined)\n```\n\n## Complex Types\n\n### Objects\n\n```typescript\nconst PersonSchema = z.object({\n  name: z.string(),\n  age: z.number(),\n  address: z.object({\n    street: z.string(),\n    city: z.string(),\n    country: z.string(),\n  }),\n});\n\ntype Person = z.infer\u003Ctypeof PersonSchema>;\n\n\u002F\u002F Object methods\nPersonSchema.shape                 \u002F\u002F Access shape\nPersonSchema.keyof()              \u002F\u002F Get union of keys\nPersonSchema.extend({ role: z.string() })  \u002F\u002F Add fields\nPersonSchema.pick({ name: true }) \u002F\u002F Pick specific fields\nPersonSchema.omit({ age: true })  \u002F\u002F Omit fields\nPersonSchema.partial()            \u002F\u002F Make all fields optional\nPersonSchema.required()           \u002F\u002F Make all fields required\nPersonSchema.deepPartial()        \u002F\u002F Recursively optional\n\n\u002F\u002F Strict vs loose objects\nz.strictObject({ ... })           \u002F\u002F No extra keys allowed (throws)\nz.object({ ... })                 \u002F\u002F Strips extra keys (default)\nz.looseObject({ ... })            \u002F\u002F Allows extra keys\n```\n\n### Arrays\n\n```typescript\nz.array(z.string())              \u002F\u002F String array\nz.array(z.number()).min(1)       \u002F\u002F At least 1 element\nz.array(z.number()).max(10)      \u002F\u002F At most 10 elements\nz.array(z.number()).length(5)    \u002F\u002F Exactly 5 elements\nz.array(z.number()).nonempty()   \u002F\u002F At least 1 element\n\n\u002F\u002F Nested arrays\nz.array(z.array(z.number()))     \u002F\u002F number[][]\n```\n\n### Tuples\n\n```typescript\nz.tuple([z.string(), z.number()]) \u002F\u002F [string, number]\nz.tuple([z.string(), z.number()]).rest(z.boolean()) \u002F\u002F [string, number, ...boolean[]]\n```\n\n### Enums and Literals\n\n```typescript\n\u002F\u002F Enum\nconst RoleEnum = z.enum([\"admin\", \"user\", \"guest\"]);\ntype Role = z.infer\u003Ctypeof RoleEnum>; \u002F\u002F \"admin\" | \"user\" | \"guest\"\n\n\u002F\u002F Literal values\nz.literal(\"exact_value\")\nz.literal(42)\nz.literal(true)\n\n\u002F\u002F Native TypeScript enum\nenum Fruits {\n  Apple,\n  Banana,\n}\nz.nativeEnum(Fruits)\n\n\u002F\u002F Enum methods\nRoleEnum.enum.admin              \u002F\u002F \"admin\"\nRoleEnum.exclude([\"guest\"])      \u002F\u002F Exclude values\nRoleEnum.extract([\"admin\", \"user\"]) \u002F\u002F Include only\n```\n\n### Unions\n\n```typescript\n\u002F\u002F Basic union\nz.union([z.string(), z.number()])\n\n\u002F\u002F Discriminated union (better performance & type inference)\nconst ResponseSchema = z.discriminatedUnion(\"status\", [\n  z.object({ status: z.literal(\"success\"), data: z.any() }),\n  z.object({ status: z.literal(\"error\"), message: z.string() }),\n]);\n\ntype Response = z.infer\u003Ctypeof ResponseSchema>;\n\u002F\u002F { status: \"success\", data: any } | { status: \"error\", message: string }\n```\n\n### Intersections\n\n```typescript\nconst BaseSchema = z.object({ id: z.string() });\nconst ExtendedSchema = z.object({ name: z.string() });\n\nconst Combined = z.intersection(BaseSchema, ExtendedSchema);\n\u002F\u002F Equivalent to: z.object({ id: z.string(), name: z.string() })\n```\n\n### Records and Maps\n\n```typescript\n\u002F\u002F Record: object with typed keys and values\nz.record(z.string())             \u002F\u002F { [key: string]: string }\nz.record(z.string(), z.number()) \u002F\u002F { [key: string]: number }\n\n\u002F\u002F Partial record (some keys optional)\nz.partialRecord(z.enum([\"a\", \"b\"]), z.string())\n\n\u002F\u002F Map\nz.map(z.string(), z.number())    \u002F\u002F Map\u003Cstring, number>\nz.set(z.string())                \u002F\u002F Set\u003Cstring>\n```\n\n## Advanced Patterns\n\n**Load `references\u002Fadvanced-patterns.md` for complete advanced validation and transformation patterns.**\n\n### Quick Reference\n\n**Refinements** (custom validation):\n```typescript\nz.string().refine((val) => val.length >= 8, \"Too short\");\nz.object({ password, confirmPassword }).superRefine((data, ctx) => { \u002F* ... *\u002F });\n```\n\n**Transformations** (modify data):\n```typescript\nz.string().transform((val) => val.trim());\nz.string().pipe(z.coerce.number());\n```\n\n**Codecs** (bidirectional transforms - NEW in v4.1):\n```typescript\nconst DateCodec = z.codec(\n  z.iso.datetime(),\n  z.date(),\n  {\n    decode: (str) => new Date(str),\n    encode: (date) => date.toISOString(),\n  }\n);\n```\n\n**Recursive Types**:\n```typescript\nconst CategorySchema: z.ZodType\u003CCategory> = z.lazy(() =>\n  z.object({ name: z.string(), subcategories: z.array(CategorySchema) })\n);\n```\n\n**Optional\u002FNullable**:\n```typescript\nz.string().optional()            \u002F\u002F string | undefined\nz.string().nullable()            \u002F\u002F string | null\nz.string().default(\"default\")    \u002F\u002F Provides default if undefined\n```\n\n**Readonly & Brand**:\n```typescript\nz.object({ ... }).readonly()     \u002F\u002F Readonly properties\nz.string().brand\u003C\"UserId\">()     \u002F\u002F Nominal typing\n```\n\n**→ Load `references\u002Fadvanced-patterns.md` for:** Complete refinement patterns, async validation, codec examples, composable schemas, conditional validation, performance optimization\n\n## Error Handling\n\n**Load `references\u002Ferror-handling.md` for complete error formatting and customization guide.**\n\n### Quick Reference\n\n**Error Formatting Methods**:\n```typescript\n\u002F\u002F For forms\nconst { fieldErrors } = z.flattenError(error);\n\n\u002F\u002F For nested data\nconst tree = z.treeifyError(error);\nconst nameError = tree.properties?.user?.properties?.name?.errors?.[0];\n\n\u002F\u002F For debugging\nconsole.log(z.prettifyError(error));\n```\n\n**Custom Error Messages** (three levels):\n```typescript\n\u002F\u002F 1. Schema-level (highest priority)\nz.string({ error: \"Custom message\" });\nz.string().min(5, \"Too short\");\n\n\u002F\u002F 2. Per-parse level\nschema.parse(data, { error: (issue) => ({ message: \"...\" }) });\n\n\u002F\u002F 3. Global level\nz.config({ customError: (issue) => ({ message: \"...\" }) });\n```\n\n**Localization** (40+ languages):\n```typescript\nz.config(z.locales.es());  \u002F\u002F Spanish\nz.config(z.locales.fr());  \u002F\u002F French\n```\n\n**→ Load `references\u002Ferror-handling.md` for:** Complete error formatting examples, custom error patterns, localization setup, error code reference\n\n## Type Inference\n\n**Load `references\u002Ftype-inference.md` for complete type inference and metadata documentation.**\n\n### Quick Reference\n\n**Basic Type Inference**:\n```typescript\nconst UserSchema = z.object({ name: z.string() });\ntype User = z.infer\u003Ctypeof UserSchema>; \u002F\u002F { name: string }\n```\n\n**Input vs Output** (for transforms):\n```typescript\nconst TransformSchema = z.string().transform((s) => s.length);\ntype Input = z.input\u003Ctypeof TransformSchema>;   \u002F\u002F string\ntype Output = z.output\u003Ctypeof TransformSchema>; \u002F\u002F number\n```\n\n**JSON Schema Conversion**:\n```typescript\nconst jsonSchema = z.toJSONSchema(UserSchema, {\n  target: \"openapi-3.0\",\n  metadata: true,\n});\n```\n\n**Metadata**:\n```typescript\n\u002F\u002F Add metadata\nconst EmailSchema = z.string().email().meta({\n  title: \"Email Address\",\n  description: \"User's email address\",\n});\n\n\u002F\u002F Create custom registry\nconst formRegistry = z.registry\u003CFormFieldMeta>();\n```\n\n**→ Load `references\u002Ftype-inference.md` for:** Complete type inference patterns, JSON Schema options, metadata system, custom registries, brand types\n\n## Functions\n\nValidate function inputs and outputs:\n\n```typescript\nconst AddFunction = z.function()\n  .args(z.number(), z.number())  \u002F\u002F Arguments\n  .returns(z.number());           \u002F\u002F Return type\n\n\u002F\u002F Implement typed function\nconst add = AddFunction.implement((a, b) => {\n  return a + b; \u002F\u002F Type-checked!\n});\n\n\u002F\u002F Async functions\nconst FetchFunction = z.function()\n  .args(z.string())\n  .returns(z.promise(z.object({ data: z.any() })))\n  .implementAsync(async (url) => {\n    const response = await fetch(url);\n    return response.json();\n  });\n```\n\n## Common Patterns\n\n### Environment Variables\n\n```typescript\nconst EnvSchema = z.object({\n  NODE_ENV: z.enum([\"development\", \"production\", \"test\"]),\n  DATABASE_URL: z.string().url(),\n  PORT: z.coerce.number().int().positive().default(3000),\n  API_KEY: z.string().min(32),\n});\n\n\u002F\u002F Validate on startup\nconst env = EnvSchema.parse(process.env);\n\n\u002F\u002F Now use typed env\nconsole.log(env.PORT); \u002F\u002F number\n```\n\n### API Request Validation\n\n```typescript\nconst CreateUserRequest = z.object({\n  username: z.string().min(3).max(20),\n  email: z.string().email(),\n  password: z.string().min(8),\n  age: z.number().int().positive().optional(),\n});\n\n\u002F\u002F Express example\napp.post(\"\u002Fusers\", async (req, res) => {\n  const result = CreateUserRequest.safeParse(req.body);\n\n  if (!result.success) {\n    return res.status(400).json({\n      errors: z.flattenError(result.error).fieldErrors,\n    });\n  }\n\n  const user = await createUser(result.data);\n  res.json(user);\n});\n```\n\n### Form Validation\n\n```typescript\nconst FormSchema = z.object({\n  firstName: z.string().min(1, \"First name required\"),\n  lastName: z.string().min(1, \"Last name required\"),\n  email: z.string().email(\"Invalid email\"),\n  age: z.coerce.number().int().min(18, \"Must be 18+\"),\n  agreeToTerms: z.literal(true, {\n    errorMap: () => ({ message: \"Must accept terms\" }),\n  }),\n});\n\ntype FormData = z.infer\u003Ctypeof FormSchema>;\n```\n\n### Partial Updates\n\n```typescript\nconst UserSchema = z.object({\n  id: z.string(),\n  name: z.string(),\n  email: z.string().email(),\n});\n\n\u002F\u002F For PATCH requests: make everything optional except id\nconst UpdateUserSchema = UserSchema.partial().required({ id: true });\n\ntype UpdateUser = z.infer\u003Ctypeof UpdateUserSchema>;\n\u002F\u002F { id: string; name?: string; email?: string }\n```\n\n### Composable Schemas\n\n```typescript\n\u002F\u002F Base schemas\nconst TimestampSchema = z.object({\n  createdAt: z.date(),\n  updatedAt: z.date(),\n});\n\nconst AuthorSchema = z.object({\n  authorId: z.string(),\n  authorName: z.string(),\n});\n\n\u002F\u002F Compose into larger schemas\nconst PostSchema = z.object({\n  id: z.string(),\n  title: z.string(),\n  content: z.string(),\n}).merge(TimestampSchema).merge(AuthorSchema);\n```\n\n## Ecosystem Integration\n\n**Load `references\u002Fecosystem-integrations.md` for complete framework and tooling integration guide.**\n\n### Quick Reference\n\n**ESLint Plugins**:\n- `eslint-plugin-zod-x` - Enforces best practices\n- `eslint-plugin-import-zod` - Enforces import style\n\n**Framework Integrations**:\n- **tRPC** - End-to-end typesafe APIs\n- **React Hook Form** - Form validation (see `react-hook-form-zod` skill)\n- **Prisma** - Generate Zod from database models\n- **NestJS** - DTOs and validation pipes\n\n**Code Generation**:\n- **orval** - OpenAPI → Zod\n- **Hey API** - OpenAPI to TypeScript + Zod\n- **kubb** - API toolkit with codegen\n\n**→ Load `references\u002Fecosystem-integrations.md` for:** Setup instructions, integration examples, Hono middleware, Drizzle ORM patterns\n\n## Troubleshooting\n\n**Load `references\u002Ftroubleshooting.md` for complete troubleshooting guide, performance tips, and best practices.**\n\n### Quick Reference\n\n**Common Issues**:\n1. TypeScript strict mode required → Enable in `tsconfig.json`\n2. Large bundle size → Use `z.lazy()` for code splitting\n3. Slow async refinements → Cache or debounce\n4. Circular dependencies → Use `z.lazy()`\n5. Slow unions → Use `z.discriminatedUnion()`\n6. Transform vs refine confusion → Use `.refine()` for validation, `.transform()` for modification\n\n**Performance Tips**:\n- Use `.discriminatedUnion()` (5-10x faster than `.union()`)\n- Cache schema instances\n- Use `.safeParse()` (avoids try-catch overhead)\n- Lazy load large schemas\n\n**Best Practices**:\n- Define schemas at module level\n- Use type inference (`z.infer`)\n- Add custom error messages\n- Validate at system boundaries\n- Compose small schemas\n- Document with `.meta()`\n\n**→ Load `references\u002Ftroubleshooting.md` for:** Detailed solutions, performance optimization, best practices, testing patterns\n\n## Quick Reference\n\n```typescript\n\u002F\u002F Primitives\nz.string(), z.number(), z.boolean(), z.date(), z.bigint()\n\n\u002F\u002F Collections\nz.array(), z.tuple(), z.object(), z.record(), z.map(), z.set()\n\n\u002F\u002F Special types\nz.enum(), z.union(), z.discriminatedUnion(), z.intersection()\nz.literal(), z.any(), z.unknown(), z.never()\n\n\u002F\u002F Modifiers\n.optional(), .nullable(), .nullish(), .default(), .catch()\n.readonly(), .brand()\n\n\u002F\u002F Validation\n.min(), .max(), .length(), .regex(), .email(), .url(), .uuid()\n.refine(), .superRefine()\n\n\u002F\u002F Transformation\n.transform(), .pipe(), .codec()\n\n\u002F\u002F Parsing\n.parse(), .safeParse(), .parseAsync(), .safeParseAsync()\n\n\u002F\u002F Type inference\nz.infer\u003Ctypeof Schema>, z.input\u003Ctypeof Schema>, z.output\u003Ctypeof Schema>\n\n\u002F\u002F Error handling\nz.flattenError(), z.treeifyError(), z.prettifyError()\n\n\u002F\u002F JSON Schema\nz.toJSONSchema(schema, options)\n\n\u002F\u002F Metadata\n.meta(), .describe()\n\n\u002F\u002F Object methods\n.extend(), .pick(), .omit(), .partial(), .required(), .merge()\n```\n\n## When to Load References\n\n**Load `references\u002Fmigration-guide.md` when:**\n- Upgrading from Zod v3 to v4\n- Questions about breaking changes\n- Need migration checklist or rollback strategy\n- Errors related to deprecated APIs (`.merge()`, `error.format()`, etc.)\n- Number validation issues with `Infinity` or unsafe integers\n\n**Load `references\u002Ferror-handling.md` when:**\n- Need to format errors for forms or UI\n- Implementing custom error messages\n- Questions about `z.flattenError()`, `z.treeifyError()`, or `z.prettifyError()`\n- Setting up localization for error messages\n- Need error code reference or pattern examples\n\n**Load `references\u002Fadvanced-patterns.md` when:**\n- Implementing custom refinements or async validation\n- Need bidirectional transformations (codecs)\n- Working with recursive types or self-referential data\n- Questions about `.refine()`, `.transform()`, or `.codec()`\n- Need performance optimization patterns\n- Implementing conditional validation\n\n**Load `references\u002Ftype-inference.md` when:**\n- Questions about TypeScript type inference\n- Need to generate JSON Schema for OpenAPI or AI\n- Implementing metadata system for forms or documentation\n- Need custom registries for type-safe metadata\n- Questions about `z.infer`, `z.input`, `z.output`\n- Using brand types for ID safety\n\n**Load `references\u002Fecosystem-integrations.md` when:**\n- Integrating with tRPC, React Hook Form, Prisma, or NestJS\n- Setting up ESLint plugins for best practices\n- Generating Zod schemas from OpenAPI (orval, Hey API, kubb)\n- Questions about Hono middleware or Drizzle ORM\n- Need framework-specific integration examples\n\n**Load `references\u002Ftroubleshooting.md` when:**\n- Encountering TypeScript strict mode errors\n- Bundle size concerns or lazy loading needs\n- Performance issues with large unions or async refinements\n- Questions about circular dependencies\n- Need best practices or testing patterns\n- Confusion between `.refine()` and `.transform()`\n\n## Additional Resources\n\n- **Official Docs**: https:\u002F\u002Fzod.dev\n- **GitHub**: https:\u002F\u002Fgithub.com\u002Fcolinhacks\u002Fzod\n- **TypeScript Playground**: https:\u002F\u002Fzod-playground.vercel.app\n- **ESLint Plugin (Best Practices)**: https:\u002F\u002Fgithub.com\u002FJoshuaKGoldberg\u002Feslint-plugin-zod-x\n- **tRPC Integration**: https:\u002F\u002Ftrpc.io\n- **Ecosystem**: https:\u002F\u002Fzod.dev\u002Fecosystem\n\n---\n\n**Production Notes**:\n- Package version: 4.1.12+ (Zod 4.x stable)\n- Zero dependencies\n- Bundle size: 2kb (gzipped)\n- TypeScript 5.5+ required\n- Strict mode required\n- Last verified: 2025-11-17\n- Skill version: 2.0.0 (Updated with v4.1 enhancements)\n\n**What's New in This Version**:\n- ✨ Comprehensive v3 to v4 migration guide with breaking changes\n- ✨ Enhanced error customization with three-level system\n- ✨ Expanded metadata API with registry system\n- ✨ Improved error formatting with practical examples\n- ✨ Built-in localization support for 40+ locales\n- ✨ Detailed codec documentation with real-world patterns\n- ✨ Performance improvements and architectural changes explained\n",{"name":5,"license":14,"metadata":23,"description":7},{"version":24,"keywords":25,"last_verified":81,"token_savings":82,"related_skills":83,"package_version":85,"errors_prevented":86,"production_tested":87},"2.0.0",[5,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80],"validation","schema","typescript","type-safety","runtime-validation","type-inference","data-validation","form-validation","api-validation","json-schema","refinement","transformation","error-handling","parse","safeParse","z.object","z.string","z.number","z.array","z.union","z.discriminatedUnion","z.refine","z.transform","z.infer","z.coerce","z.enum","z.literal","z.tuple","z.record","z.intersection","z.codec","z.toJSONSchema","z.treeifyError","z.flattenError","z.prettifyError","z.registry","z.globalRegistry",".register",".meta","error-customization","localization","i18n","migration","v3-to-v4","breaking-changes","tRPC","prisma-zod","react-hook-form","trpc","environment-variables","env-validation","config-validation","dto","type-guard","runtime-type-checking",1763337600000,"65%",[84],"react-hook-form-zod","4.1.12+",8,true,"main","9f54582c8b485462d402d7e70feaef34801746b9",".opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web","https:\u002F\u002Fgithub.com\u002Faibizmod","2026-09-24 00:48:11",{"source":8,"skillName":5,"commands":95,"prompt":105,"zipAvailable":87},[96,99,102],{"tool":97,"command":98},"npx","npx skills add aibizmod\u002Faibizmod-service-web --skill zod",{"tool":100,"command":101},"bunx","bunx skills add aibizmod\u002Faibizmod-service-web --skill zod",{"tool":103,"command":104},"pnpm","pnpm dlx skills add aibizmod\u002Faibizmod-service-web --skill zod","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002FSKILL.md",[107,113,119,123,127,131,135,139,143,147],{"path":108,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":111,"sourceHtmlUrl":112},"references\u002Fadvanced-patterns.md","REFERENCE","参考文档",13470,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Fadvanced-patterns.md",{"path":114,"resourceType":115,"resourceTypeDesc":116,"sizeBytes":117,"sourceHtmlUrl":118},"references\u002Fcommon-patterns.ts","SCRIPT","脚本",11232,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Fcommon-patterns.ts",{"path":120,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":121,"sourceHtmlUrl":122},"references\u002Fecosystem-integrations.md",9379,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Fecosystem-integrations.md",{"path":124,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":125,"sourceHtmlUrl":126},"references\u002Ferror-handling.md",12564,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Ferror-handling.md",{"path":128,"resourceType":115,"resourceTypeDesc":116,"sizeBytes":129,"sourceHtmlUrl":130},"references\u002Feslint.config.js",1643,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Feslint.config.js",{"path":132,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":133,"sourceHtmlUrl":134},"references\u002Fmigration-guide.md",8535,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Fmigration-guide.md",{"path":136,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":137,"sourceHtmlUrl":138},"references\u002Fquick-reference.md",8195,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Fquick-reference.md",{"path":140,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":141,"sourceHtmlUrl":142},"references\u002Ftroubleshooting.md",12713,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Ftroubleshooting.md",{"path":144,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":145,"sourceHtmlUrl":146},"references\u002Ftsconfig.json",1211,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Ftsconfig.json",{"path":148,"resourceType":109,"resourceTypeDesc":110,"sizeBytes":149,"sourceHtmlUrl":150},"references\u002Ftype-inference.md",10676,"https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzod\u002Fskills\u002Fzod\u002Freferences\u002Ftype-inference.md",[152,159,166,173,180,187],{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":18},"01M7846EAPZWCQ8C6G3AAMMR57","{TODO=lowercase-hyphen-case-name}","[TODO: Write comprehensive description in third-person. Start with \"This skill provides...\" or \"This skill should be used when...\"]\n\n[TODO: Add \"Use when\" scenarios - specific situations where Claude should use this skill]\n\n[TODO: Add keywords - technologies, use cases, error messages that should trigger this skill]","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Ftemplates\u002Fskill-skeleton\u002Fskills\u002Fskill-name\u002FSKILL.md",[],[],{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":165,"publishedAt":18},"01M7846A0WGDKJTDPD5QMHQVFV","zustand-state-management","Zustand state management for React with TypeScript. Use for global state, Redux\u002FContext API migration, localStorage persistence, slices pattern, devtools, Next.js SSR, or encountering hydration errors, TypeScript inference issues, persist middleware problems, infinite render loops.","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fzustand-state-management\u002Fskills\u002Fzustand-state-management\u002FSKILL.md",[],[],{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":18},"01M7845ZX17SVNNY7EDGPJHSBT","xss-prevention","XSS attack prevention with input sanitization, output encoding, Content Security Policy. Use for user-generated content, rich text editors, web application security, or encountering stored XSS, reflected XSS, DOM manipulation, script injection errors.","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fxss-prevention\u002Fskills\u002Fxss-prevention\u002FSKILL.md",[],[],{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":179,"publishedAt":18},"01M7845ST1H37YHSXWWQ9N0V0S","wordpress-plugin-core","WordPress plugin development with hooks, security, REST API, custom post types. Use for plugin creation, $wpdb queries, Settings API, or encountering SQL injection, XSS, CSRF, nonce errors.","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fwordpress-plugin-core\u002Fskills\u002Fwordpress-plugin-core\u002FSKILL.md",[],[],{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":18},"01M7845PTWD5HWSTGP35Q8TFNY","woocommerce-dev-cycle","Run tests, linting, and quality checks for WooCommerce development. Use when running tests, fixing code style, or following the development workflow in WooCommerce projects.","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fwoocommerce-dev-cycle\u002Fskills\u002Fwoocommerce-dev-cycle\u002FSKILL.md",[],[],{"skillNo":188,"name":189,"nameZh":6,"description":190,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":191,"categories":192,"keywords":193,"publishedAt":18},"01M7845KJNR2PRNRW6T3040Y0P","woocommerce-copy-guidelines","Guidelines for UI text and copy in WooCommerce. Use when writing user-facing text, labels, buttons, messages, or documentation in WooCommerce projects.","https:\u002F\u002Fgithub.com\u002Faibizmod\u002Faibizmod-service-web\u002Fblob\u002Fmain\u002F.opencode\u002Fskill\u002Fclaude-skills\u002Fplugins\u002Fwoocommerce-copy-guidelines\u002Fskills\u002Fwoocommerce-copy-guidelines\u002FSKILL.md",[],[]]