Zod校验
zod-validation-utilities
by giuseppe-trisciuoglio
沉淀 Zod v4 在 TypeScript 中的高复用校验模式,适合给 API、表单、配置和外部输入搭建类型安全的验证层,统一处理 coercion、transform、跨字段约束和错误信息。
安装
claude skill add --url github.com/giuseppe-trisciuoglio/developer-kit/tree/main/plugins/developer-kit-typescript/skills/zod-validation-utilities文档
Zod Validation Utilities
Overview
Production-ready Zod v4 patterns for reusable, type-safe validation with minimal boilerplate. Focuses on modern APIs, predictable error handling, and form integration.
When to Use
- Defining request/response validation schemas in TypeScript services
- Parsing untrusted input from APIs, forms, env vars, or external systems
- Standardizing coercion, transforms, and cross-field validation
- Building reusable schema utilities across teams
- Integrating React Hook Form with Zod using
zodResolver
Instructions
- Start with strict object schemas and explicit field constraints
- Prefer modern Zod v4 APIs and the
erroroption for error messages - Use coercion at boundaries (
z.coerce.*) when input types are uncertain - Keep business invariants in
refine/superRefineclose to schema definitions - Export both schema and inferred types (
z.input/z.output) for consistency - Reuse utility schemas (email, id, dates, pagination) to reduce duplication
Examples
1) Modern Zod 4 primitives and object errors
import { z } from "zod";
export const UserIdSchema = z.uuid({ error: "Invalid user id" });
export const EmailSchema = z.email({ error: "Invalid email" });
export const WebsiteSchema = z.url({ error: "Invalid URL" });
export const UserProfileSchema = z.object(
{
id: UserIdSchema,
email: EmailSchema,
website: WebsiteSchema.optional(),
},
{ error: "Invalid user profile payload" }
);
2) Coercion, preprocess, and transform
import { z } from "zod";
export const PaginationQuerySchema = z.object({
page: z.coerce.number().int().min(1).default(1),
pageSize: z.coerce.number().int().min(1).max(100).default(20),
includeArchived: z.coerce.boolean().default(false),
});
export const DateFromUnknownSchema = z.preprocess(
(value) => (typeof value === "string" || value instanceof Date ? value : undefined),
z.coerce.date({ error: "Invalid date" })
);
export const NormalizedEmailSchema = z
.string()
.trim()
.toLowerCase()
.email({ error: "Invalid email" })
.transform((value) => value as Lowercase<string>);
3) Complex schema structures
import { z } from "zod";
const TagSchema = z.string().trim().min(1).max(40);
export const ProductSchema = z.object({
sku: z.string().min(3).max(24),
tags: z.array(TagSchema).max(15),
attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
dimensions: z.tuple([z.number().positive(), z.number().positive(), z.number().positive()]),
});
export const PaymentMethodSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal("card"), last4: z.string().regex(/^\d{4}$/) }),
z.object({ type: z.literal("paypal"), email: z.email() }),
z.object({ type: z.literal("wire"), iban: z.string().min(10) }),
]);
4) refine and superRefine
import { z } from "zod";
export const PasswordSchema = z
.string()
.min(12)
.refine((v) => /[A-Z]/.test(v), { error: "Must include an uppercase letter" })
.refine((v) => /\d/.test(v), { error: "Must include a number" });
export const RegisterSchema = z
.object({
email: z.email(),
password: PasswordSchema,
confirmPassword: z.string(),
})
.superRefine((data, ctx) => {
if (data.password !== data.confirmPassword) {
ctx.addIssue({
code: "custom",
path: ["confirmPassword"],
message: "Passwords do not match",
});
}
});
5) Optional, nullable, nullish, and default
import { z } from "zod";
export const UserPreferencesSchema = z.object({
nickname: z.string().min(2).optional(), // undefined allowed
bio: z.string().max(280).nullable(), // null allowed
avatarUrl: z.url().nullish(), // null or undefined allowed
locale: z.string().default("en"), // fallback when missing
});
6) React Hook Form integration (zodResolver)
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const ProfileFormSchema = z.object({
name: z.string().min(2, { error: "Name too short" }),
email: z.email({ error: "Invalid email" }),
age: z.coerce.number().int().min(18),
});
type ProfileFormInput = z.input<typeof ProfileFormSchema>;
type ProfileFormOutput = z.output<typeof ProfileFormSchema>;
const form = useForm<ProfileFormInput, unknown, ProfileFormOutput>({
resolver: zodResolver(ProfileFormSchema),
criteriaMode: "all",
});
Best Practices
- Keep schemas near boundaries (HTTP handlers, queues, config loaders)
- Prefer
safeParsefor recoverable flows;parsefor fail-fast execution - Share small schema utilities (
id,email,slug) to enforce consistency - Use
z.inputandz.outputwhen transforms/coercions change runtime shape - Avoid overusing
preprocess; prefer explicitz.coerce.*where possible - Treat external payloads as untrusted and always validate before use
Constraints and Warnings
- Ensure examples match your installed
zodmajor version (v4 APIs shown) erroris the preferred option for custom errors in Zod v4 patterns- Discriminated unions require a stable discriminator key across variants
- Coercion can hide bad upstream data; add bounds and refinements defensively
相关 Skills
网页构建器
by anthropics
面向复杂 claude.ai HTML artifact 开发,快速初始化 React + Tailwind CSS + shadcn/ui 项目并打包为单文件 HTML,适合需要状态管理、路由或多组件交互的页面。
✎ 在 claude.ai 里做复杂网页 Artifact 很省心,多组件、状态和路由都能顺手搭起来,React、Tailwind 与 shadcn/ui 组合效率高、成品也更精致。
前端设计
by anthropics
面向组件、页面、海报和 Web 应用开发,按鲜明视觉方向生成可直接落地的前端代码与高质感 UI,适合做 landing page、Dashboard 或美化现有界面,避开千篇一律的 AI 审美。
✎ 想把页面做得既能上线又有设计感,就用前端设计:组件到整站都能产出,难得的是能避开千篇一律的 AI 味。
网页应用测试
by anthropics
用 Playwright 为本地 Web 应用编写自动化测试,支持启动开发服务器、校验前端交互、排查 UI 异常、抓取截图与浏览器日志,适合调试动态页面和回归验证。
✎ 借助 Playwright 一站式验证本地 Web 应用前端功能,调 UI 时还能同步查看日志和截图,定位问题更快。
相关 MCP 服务
GitHub
编辑精选by GitHub
GitHub 是 MCP 官方参考服务器,让 Claude 直接读写你的代码仓库和 Issues。
✎ 这个参考服务器解决了开发者想让 AI 安全访问 GitHub 数据的问题,适合需要自动化代码审查或 Issue 管理的团队。但注意它只是参考实现,生产环境得自己加固安全。
Context7 文档查询
编辑精选by Context7
Context7 是实时拉取最新文档和代码示例的智能助手,让你告别过时资料。
✎ 它能解决开发者查找文档时信息滞后的问题,特别适合快速上手新库或跟进更新。不过,依赖外部源可能导致偶尔的数据延迟,建议结合官方文档使用。
by tldraw
tldraw 是让 AI 助手直接在无限画布上绘图和协作的 MCP 服务器。
✎ 这解决了 AI 只能输出文本、无法视觉化协作的痛点——想象让 Claude 帮你画流程图或白板讨论。最适合需要快速原型设计或头脑风暴的开发者。不过,目前它只是个基础连接器,你得自己搭建画布应用才能发挥全部潜力。