← Browse

@mindrally/zod-schema-validation

A

Best practices for Zod schema validation and type inference in TypeScript applications.

skillclaude

Install

agr install @mindrally/zod-schema-validation --target claude

Writes 1 file into .claude/skills/, pinned to git-b18a2bdb.

  • .claude/skills/zod-schema-validation/SKILL.md

Document


name: zod-schema-validation description: Best practices for Zod schema validation and type inference in TypeScript applications.

Zod Schema Validation

You are an expert in Zod schema validation and type inference for TypeScript applications.

Core Principles

  • Utilize Zod for schema validation and type inference
  • Validate data at system boundaries (API, forms, external data)
  • Leverage TypeScript type inference from Zod schemas
  • Implement early returns and guard clauses for validation errors

Schema Design

Basic Schema

import { z } from 'zod'

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().positive().optional(),
  role: z.enum(['admin', 'user', 'guest']),
  createdAt: z.date(),
})

type User = z.infer<typeof UserSchema>

Best Practices

  • Define schemas close to where they're used
  • Use .infer to derive TypeScript types
  • Compose schemas using .extend(), .merge(), .pick(), .omit()
  • Create reusable base schemas for common patterns

Validation Patterns

Safe Parsing

const result = UserSchema.safeParse(data)
if (!result.success) {
  console.error(result.error.format())
  return
}
// result.data is typed as User

Transform and Refine

const schema = z.string()
  .transform((val) => val.trim().toLowerCase())
  .refine((val) => val.length > 0, 'Cannot be empty')

Form Integration

  • Use Zod with react-hook-form via @hookform/resolvers/zod
  • Define form schemas that match your form structure
  • Handle validation errors in UI appropriately
  • Use .partial() for optional update forms

API Validation

  • Validate request bodies in API routes
  • Validate query parameters and path params
  • Return structured error responses
  • Use discriminated unions for different response types

Error Handling

  • Implement custom error messages for better UX
  • Use .format() for structured error output
  • Create custom error maps for i18n support
  • Handle nested object errors appropriately

Advanced Patterns

Discriminated Unions

const ResultSchema = z.discriminatedUnion('status', [
  z.object({ status: z.literal('success'), data: UserSchema }),
  z.object({ status: z.literal('error'), message: z.string() }),
])

Recursive Schemas

const CategorySchema: z.ZodType<Category> = z.lazy(() =>
  z.object({
    name: z.string(),
    children: z.array(CategorySchema),
  })
)

Performance

  • Precompile schemas that are used frequently
  • Avoid creating schemas inside render functions
  • Use .passthrough() or .strict() intentionally
  • Consider partial validation for large objects

Trustgrade A

  • passBody integrity

    Whether the stored document is plausibly the kind of file the artifact declares, rather than something fetched by mistake.

  • passType matchnot applicable to this artifact type

    Whether the artifact is really the kind of thing its metadata claims it is.

  • passFreshness

    How long since the source repository was last pushed to.

  • passPrompt injection

    Scans the artifact's own text for instructions aimed at your agent rather than at you.

  • passLicense

    Whether the source repository declares an SPDX license permissive enough to redistribute.

How the grade is calculated

Each check contributes 0 points when it passes, 1 when it warns, and 2 when it fails. The total maps to a letter:

  • Aevery check passed
  • Bone warning
  • Ctwo warnings
  • Dprompt injection or body integrity failed, or three warnings
  • Fone of those failed, and something else is wrong

These are automated hygiene checks, not a security audit, and not a dependency or vulnerability scan. A grade of A means nothing was flagged — not that the artifact is safe.

Versions

  • git-b18a2bdb12d12026-07-31