Skip to content
Back to skills

Zod

ASecurity

You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.

  • 142 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 6, 2026
developmenttypescriptgobashnodeexpressapidatabasebackend

Works with

  • terminal
  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned September 6, 2026

npx -y skills add TerminalSkills/skills --skill zod --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Zod?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Zod
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terminalskills-zod/badge)](https://www.skillsdirectory.com/skills/terminalskills-zod)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: zod
description: >-
  You are an expert in Zod, the TypeScript-first schema declaration and
  validation library. You help developers define schemas that validate data at
  runtime AND infer TypeScript types at compile time — eliminating the need to
  write types and validators separately. Used for API input validation, form
  validation, environment variables, config files, and any data boundary.
license: Apache-2.0
compatibility: ''
metadata:
  author: terminal-skills
  version: 1.0.0
  category: Backend Development
  tags:
    - validation
    - schema
    - typescript
    - type-inference
    - parsing
    - forms
---

# Zod — TypeScript-First Schema Validation

You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.

## Core Capabilities

### Schema Definition

```typescript
import { z } from "zod";

// Primitives
const nameSchema = z.string().min(1).max(100);
const ageSchema = z.number().int().positive().max(150);
const emailSchema = z.string().email();

// Objects
const userSchema = z.object({
  name: z.string().min(1, "Name is required"),
  email: z.string().email("Invalid email"),
  age: z.number().int().min(18, "Must be 18+").optional(),
  role: z.enum(["user", "admin", "moderator"]).default("user"),
  tags: z.array(z.string()).max(10).default([]),
  address: z.object({
    street: z.string(),
    city: z.string(),
    country: z.string().length(2),          // ISO country code
    zip: z.string().regex(/^\d{5}(-\d{4})?$/),
  }).optional(),
  metadata: z.record(z.string(), z.unknown()).optional(),
});

// Infer TypeScript type from schema — single source of truth
type User = z.infer<typeof userSchema>;
// {
//   name: string; email: string; age?: number;
//   role: "user" | "admin" | "moderator"; tags: string[];
//   address?: { street: string; city: string; country: string; zip: string };
//   metadata?: Record<string, unknown>;
// }

// Parse (throws on invalid)
const user = userSchema.parse(requestBody);

// Safe parse (returns result object)
const result = userSchema.safeParse(requestBody);
if (result.success) {
  console.log(result.data);                // Typed as User
} else {
  console.log(result.error.flatten());     // Structured error messages
}
```

### Advanced Patterns

```typescript
// Discriminated unions
const eventSchema = z.discriminatedUnion("type", [
  z.object({ type: z.literal("click"), x: z.number(), y: z.number() }),
  z.object({ type: z.literal("scroll"), offset: z.number() }),
  z.object({ type: z.literal("keypress"), key: z.string(), modifiers: z.array(z.string()) }),
]);

// Transform (parse + transform in one step)
const dateStringSchema = z.string().transform((s) => new Date(s));
const csvSchema = z.string().transform((s) => s.split(",").map((v) => v.trim()));

// Refinement (custom validation)
const passwordSchema = z.string()
  .min(8, "At least 8 characters")
  .refine((p) => /[A-Z]/.test(p), "Must contain uppercase")
  .refine((p) => /[0-9]/.test(p), "Must contain number")
  .refine((p) => /[^A-Za-z0-9]/.test(p), "Must contain special character");

// Recursive types
const categorySchema: z.ZodType<Category> = z.object({
  name: z.string(),
  children: z.lazy(() => z.array(categorySchema)).default([]),
});

// Environment variables
const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  API_KEY: z.string().min(1),
  PORT: z.coerce.number().default(3000),   // Coerces string "3000" to number
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
});
const env = envSchema.parse(process.env);

// Pipe (chain transformations)
const numberFromString = z.string().pipe(z.coerce.number().positive());
```

### API Validation

```typescript
// Express middleware
import { z } from "zod";

function validate<T extends z.ZodType>(schema: T) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body);
    if (!result.success) {
      return res.status(400).json({ errors: result.error.flatten().fieldErrors });
    }
    req.body = result.data;
    next();
  };
}

app.post("/api/users", validate(userSchema), (req, res) => {
  // req.body is validated and typed
});
```

## Installation

```bash
npm install zod
```

## Best Practices

1. **Single source of truth** — Define schema once; infer types with `z.infer<>`; never duplicate type definitions
2. **safeParse over parse** — Use `safeParse` in APIs; returns error object instead of throwing
3. **Coerce for strings** — Use `z.coerce.number()` for query params and env vars; auto-converts strings
4. **Default values** — Use `.default()` to provide defaults; schema is also a transformer
5. **Error messages** — Pass custom messages: `z.string().min(1, "Required")`; user-friendly validation
6. **Discriminated unions** — Use for API event types, polymorphic data; TypeScript narrows correctly
7. **Environment validation** — Validate `process.env` at startup; fail fast on missing config
8. **Composability** — `.extend()`, `.pick()`, `.omit()`, `.merge()` for schema reuse; DRY schemas

Files in this skill

  • SKILL.md5.3 KB
  • _scores.json1.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…