mcpField
Z
zod

zod

github.com/marcioaltoe开发061 次安装1 天前更新
代码仓库

关于 zod

Zod 是面向 TypeScript 的模式验证库,供需要运行时数据检查和类型推导的开发者使用。其 API 涵盖解析、验证、转换和 JSON Schema 转换,并提供支持摇树优化的 Mini 版本。

主要功能

  1. 01运行时解析与验证
  2. 02从模式推导类型
  3. 03数据转换与双向编解码
  4. 04导入和导出 JSON Schema
  5. 05支持摇树优化的 Zod Mini

适用场景

  1. 01运行时校验输入数据
  2. 02根据模式推导 TypeScript 类型
  3. 03与 JSON Schema 相互转换

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/marcioaltoe/skills --skill zod

安装后在 Claude Code 中输入/zod确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
advanced.md
codecs.md
json-schema.md
migration.md
zod-mini.md

详细介绍

Zod 4

TypeScript 优先的模式验证。核心包体积为 2kb(gzip 压缩后)。零依赖。

重要:Zod 4 是当前稳定版本(zod@^4.0.0)。始终编写 Zod 4 代码。切勿使用已弃用的 Zod 3 模式。

导入

import * as z from "zod";

适用于支持 tree-shaking 的版本(包体积更小):

import * as z from "zod/mini";

核心模式

解析
schema.parse(data);           // throws ZodError on failure
schema.safeParse(data);       // returns { success, data?, error? }
await schema.parseAsync(data);
await schema.safeParseAsync(data);
类型推断
type MyType = z.infer<typeof mySchema>;    // output type
type MyInput = z.input<typeof mySchema>;   // input type
type MyOutput = z.output<typeof mySchema>; // same as z.infer
基本类型
z.string();
z.number();      // finite numbers only (no Infinity, no NaN)
z.bigint();
z.boolean();
z.symbol();
z.undefined();
z.null();
z.date();
z.nan();
强制转换
z.coerce.string();    // String(input)
z.coerce.number();    // Number(input)
z.coerce.boolean();   // Boolean(input)
z.coerce.bigint();    // BigInt(input)
z.coerce.date();      // new Date(input)

字符串格式(顶层)

使用顶层函数,而不是方法。像 z.string().email() 这样的方法已弃用。

// CORRECT (Zod 4)
z.email();
z.uuid();
z.url();
z.httpUrl();
z.hostname();
z.emoji();
z.base64();
z.base64url();
z.hex();
z.jwt();
z.nanoid();
z.cuid();
z.cuid2();
z.ulid();
z.ipv4();
z.ipv6();
z.mac();
z.cidrv4();
z.cidrv6();
z.hash("sha256");     // "sha1" | "sha384" | "sha512" | "md5"
z.e164();              // phone numbers
z.iso.date();
z.iso.time();
z.iso.datetime();
z.iso.duration();

// DEPRECATED (Zod 3 style — do NOT use)
z.string().email();    // ❌
z.string().uuid();     // ❌
z.string().url();      // ❌
UUID 版本
z.uuid();                    // any RFC 9562/4122 UUID
z.uuid({ version: "v4" });  // specific version
z.uuidv4();                  // convenience
z.uuidv6();
z.uuidv7();
z.guid();                    // any 8-4-4-4-12 hex pattern (less strict)
自定义电子邮件正则表达式
z.email();                                     // default (Gmail rules)
z.email({ pattern: z.regexes.html5Email });    // browser-style
z.email({ pattern: z.regexes.rfc5322Email });  // RFC 5322
z.email({ pattern: z.regexes.unicodeEmail });  // intl emails
JWT
z.jwt();
z.jwt({ alg: "HS256" });

数字与整数

z.number();      // any finite number
z.int();         // safe integer range
z.int32();       // int32 range
z.float32();     // float32 range
z.float64();     // float64 range

// bigint variants
z.bigint();
z.int64();
z.uint64();
数字验证
z.number().gt(5);
z.number().gte(5);          // alias: .min(5)
z.number().lt(5);
z.number().lte(5);          // alias: .max(5)
z.number().positive();
z.number().nonnegative();
z.number().negative();
z.number().nonpositive();
z.number().multipleOf(5);   // alias: .step(5)
字符串验证
z.string().max(5);
z.string().min(5);
z.string().length(5);
z.string().regex(/pattern/);
z.string().startsWith("abc");
z.string().endsWith("xyz");
z.string().includes("---");
z.string().uppercase();
z.string().lowercase();
z.string().trim();
z.string().toLowerCase();
z.string().toUpperCase();
z.string().normalize();

对象

z.object({ name: z.string(), age: z.number() });          // strips unknown keys
z.strictObject({ name: z.string() });                      // errors on unknown keys
z.looseObject({ name: z.string() });                       // passes unknown keys through

已弃用:.strict()、.passthrough()、.strip()、.merge()、.deepPartial()。

对象方法
schema.extend({ newField: z.string() });    // add fields
schema.pick({ name: true });                // pick fields
schema.omit({ age: true });                 // omit fields
schema.partial();                           // all optional
schema.partial({ name: true });             // some optional
schema.required();                          // all required
schema.keyof();                             // ZodEnum from keys
schema.shape.name;                          // access inner schema

为获得最佳的 tsc 性能,建议使用展开语法:

z.object({ ...Base.shape, ...Extra.shape, newField: z.string() });
递归对象
const Category = z.object({
  name: z.string(),
  get subcategories() {
    return z.array(Category);
  },
});

枚举

z.enum(["A", "B", "C"]);               // string enum
z.enum(MyTSEnum);                       // TypeScript enum (replaces z.nativeEnum())
z.enum({ A: 0, B: 1 } as const);       // enum-like object

已弃用:z.nativeEnum()。请改用 z.enum()。

数组、元组、集合、映射

z.array(z.string());
z.array(z.string()).min(1).max(10).length(5);
z.tuple([z.string(), z.number()]);
z.tuple([z.string()], z.number());    // variadic: [string, ...number[]]
z.set(z.number());
z.map(z.string(), z.number());

联合与交集

z.union([z.string(), z.number()]);
z.discriminatedUnion("status", [
  z.object({ status: z.literal("ok"), data: z.string() }),
  z.object({ status: z.literal("err"), error: z.string() }),
]);
z.xor([z.string(), z.number()]);          // exclusive union (exactly one match)
z.intersection(schemaA, schemaB);

记录

z.record(z.string(), z.number());                    // Record<string, number>
z.record(z.enum(["a", "b"]), z.string());            // exhaustive: { a: string; b: string }
z.partialRecord(z.enum(["a", "b"]), z.string());     // partial: { a?: string; b?: string }
z.looseRecord(z.string().regex(/^x_/), z.number());  // pass through non-matching keys

重大变更:已移除单参数形式 z.record(z.string())。始终同时传入键和值的模式。

字面量

z.literal("hello");
z.literal(42);
z.literal(true);
z.literal(["a", "b", "c"]);   // multi-value literal (new in Zod 4)

文件

z.file();
z.file().min(10_000);                          // min size in bytes
z.file().max(1_000_000);                       // max size in bytes
z.file().mime("image/png");                    // single MIME
z.file().mime(["image/png", "image/jpeg"]);    // multiple MIMEs

字符串布尔值

z.stringbool();    // "true"/"yes"/"1"/"on"/"y"/"enabled" → true, inverses → false
z.stringbool({ truthy: ["yes", "y"], falsy: ["no", "n"] });
z.stringbool({ case: "sensitive" });

模板字面量

z.templateLiteral(["hello, ", z.string()]);                    // `hello, ${string}`
z.templateLiteral([z.number(), z.enum(["px", "em", "rem"])]);  // `${number}px` | ...

可选、可空、默认值

z.optional(z.string());          // or z.string().optional()
z.nullable(z.string());          // or z.string().nullable()
z.nullish(z.string());           // optional + nullable

z.string().default("hello");     // short-circuits on undefined, returns output type
z.string().prefault("hello");    // pre-parse default, runs through validation
z.number().catch(42);            // fallback on any validation error

重大变更:.default() 现在接受输出类型,而非输入类型。要使用旧行为,请用 .prefault()。

转换与管道

z.transform((val) => String(val));                      // standalone transform
z.string().transform((val) => val.length);              // pipe string → transform
z.preprocess((val) => String(val), z.string());         // transform → pipe to schema
z.string().pipe(z.transform((val) => val.length));      // explicit pipe

// .overwrite() — transform without changing inferred type
z.number().overwrite((val) => val ** 2);

编解码器(双向转换)

Zod 4.1 新增。定义编码/解码对:

const stringToDate = z.codec(z.iso.datetime(), z.date(), {
  decode: (s) => new Date(s),
  encode: (d) => d.toISOString(),
});

stringToDate.decode("2024-01-15T10:30:00.000Z");  // → Date
stringToDate.encode(new Date());                    // → string
stringToDate.parse("2024-01-15T10:30:00.000Z");    // → Date (same as decode at runtime)

错误自定义

使用统一的 error 参数(取代 message、errorMap、invalid_type_error、required_error):

z.string().min(5, { error: "Too short" });
z.string({ error: (issue) => issue.input === undefined ? "Required" : "Not a string" });
z.string({ error: (issue) => {
  if (issue.code === "too_small") return `Min ${issue.minimum}`;
}});

已弃用:message、errorMap、invalid_type_error、required_error。

元数据与注册表

z.string().meta({ id: "email", title: "Email", description: "User email" });
z.string().describe("A description");      // shorthand for .meta({ description: ... })

// Custom registries
const myReg = z.registry<{ description: string }>();
z.string().register(myReg, { description: "..." });

JSON Schema

z.toJSONSchema(schema);                                        // Zod → JSON Schema
z.toJSONSchema(schema, { target: "draft-07" });                // specific draft
z.toJSONSchema(schema, { target: "openapi-3.0" });             // OpenAPI 3.0
z.fromJSONSchema(jsonSchema);                                  // JSON Schema → Zod (experimental)

细化

z.string().refine((val) => val.includes("@"), { error: "Must contain @" });
z.string().refine((val) => val.includes("@"), { error: "...", abort: true }); // stop on failure
z.array(z.string()).superRefine((val, ctx) => {
  ctx.addIssue({ code: "custom", message: "...", input: val });
});

细化现在位于模式内部(不再由 ZodEffects 包装)。可以将 .refine() 与其他方法交错使用:

z.string().refine(v => v.includes("@")).min(5);  // works in Zod 4!

错误美化输出

z.prettifyError(zodError);   // formatted multi-line string
z.treeifyError(zodError);    // tree structure (replaces .format() and .flatten())

更多参考

  • Zod Mini:参见 references/zod-mini.md,了解支持 tree-shaking 的 API 差异、.check() 用法和包体积权衡
  • 编解码器:参见 references/codecs.md,了解双向转换、编码行为和常见编解码器模式(stringToDate、jsonCodec 等)
  • JSON Schema:参见 references/json-schema.md,了解 z.toJSONSchema() 选项、格式转换、基于注册表的多模式以及 z.fromJSONSchema()
  • 高级模式:参见 references/advanced.md,了解注册表、细化 when、.superRefine()、.check()、函数、品牌类型、只读、自定义模式以及高级字符串/对象/记录/联合选项
  • 从 Zod 3 迁移:参见 references/migration.md,了解所有重大变更和已弃用的 API

评论

支持 Markdown