关于 zod-validation-utilities
面向 TypeScript 开发者的 Zod v4 验证模式技能,指导构建可复用、类型安全的 schema。涵盖错误处理、输入转换及 React Hook Form 集成。
主要功能
- 01Zod v4 schema 定义
- 02输入强制转换与转换
- 03refine 跨字段校验
- 04safeParse 错误处理
- 05React Hook Form 集成
- 06推断输入与输出类型
适用场景
- 01验证 API 请求与响应
- 02解析表单及环境变量
- 03复用团队验证 schema
- 04在 React Hook Form 中校验表单
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill zod-validation-utilities安装后在 Claude Code 中输入/zod-validation-utilities确认已加载。
附带文件references/advanced-patterns.md
详细介绍
Zod 验证实用工具
概述
生产就绪的 Zod v4 模式,可用最少的样板代码实现可复用且类型安全的验证。重点介绍现代 API、可预测的错误处理和表单集成。
适用场景
- 在 TypeScript 服务中定义请求/响应验证模式
- 解析来自 API、表单、环境变量或外部系统的不可信输入
- 统一强制转换、转换和跨字段验证
- 在团队之间构建可复用的模式实用工具
- 使用
zodResolver将 React Hook Form 与 Zod 集成
使用说明
- 从严格的对象模式和明确的字段约束开始
- 优先使用现代 Zod v4 API 和
error选项设置错误消息 - 在边界处使用强制转换(
z.coerce.*),处理类型不确定的输入 - 将业务不变量放在靠近模式定义的
refine/superRefine中 - 同时导出模式和推断类型(
z.input/z.output),以保持一致 - 复用实用模式(电子邮件、ID、日期、分页),减少重复
验证工作流
将验证集成到 API 处理程序或服务时:
- 定义边界处的模式(处理程序、队列、配置加载器)
- 使用
safeParse解析,以妥善处理错误 - 检查
result.success,根据成功或失败进行分支处理 - 在成功路径中使用
result.data,并享受完整的类型推断 - 返回格式化后的错误,或继续处理已验证的数据
完整模式请参见示例 7(safeParse 工作流)。
示例
1) 现代 Zod 4 原始类型与对象错误
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) 强制转换、预处理与转换
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) 复杂模式结构
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 与 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) 可选、可空、空值可选与默认值
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 集成(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",
});
7) 使用 safeParse 的错误处理工作流
import { z } from "zod";
import type { ZodError } from "zod";
const ResultSchema = z.object({ id: z.string(), name: z.string() });
function parseAndHandle(input: unknown) {
const result = ResultSchema.safeParse(input);
if (!result.success) {
const error = result.error as ZodError;
console.error("Validation failed:", error.errors);
return { success: false as const, error: error.format() };
}
return { success: true as const, data: result.data };
}
提示:有关高级判别联合模式和复杂的 React Hook Form 工作流,请参见
references/advanced-patterns.md。
最佳实践
- 将模式放在靠近边界的位置(HTTP 处理程序、队列、配置加载器)
- 可恢复的流程优先使用
safeParse;需要快速失败时使用parse - 共享小型模式实用工具(
id、email、slug),以确保一致性 - 转换/强制转换会改变运行时结构时,使用
z.input和z.output - 避免过度使用
preprocess;尽可能优先使用明确的z.coerce.* - 将外部载荷视为不可信数据,并始终在使用前进行验证
限制与警告
- 确保示例与已安装的
zod主版本匹配(此处展示 v4 API) - 在 Zod v4 模式中,
error是自定义错误的首选选项 - 判别联合要求各变体使用稳定的判别键
- 强制转换可能会掩盖上游的错误数据;请添加边界限制和细化验证,做好防护
评论
支持 Markdown