zod

库

colinhacks/zod

基于TypeScript的运行时数据校验库,支持静态类型推断。

项目简介

Zod 是一个 TypeScript 优先的 schema 校验库,能从定义中自动推断静态类型。它提供简洁不可变的 API,以强类型安全解析和验证不可信数据,零依赖并支持 JSON Schema,可在 Node.js 和现代浏览器中使用。

README 预览

\n  \n  Zod\n  \n    TypeScript-first schema validation with static type inference\n    \n    by @colinhacks\n  \n\n\n\n\n\n\n\n\n\n\n\n\n  Docs\n    •  \n  Discord\n    •  \n  𝕏\n    •  \n  Bluesky\n  \n\n\n\n\n\n### [Read the docs →](https://zod.dev/api)\n\n\n\n\n## What is Zod?\n\nZod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.\n\n```ts\nimport * as z from "zod";\n\nconst User = z.object({\n  name: z.string(),\n});\n\n// some untrusted data...\nconst input = {\n  /* stuff */\n};\n\n// the parsed result is validated and type safe!\nconst data = User.parse(input);\n\n// so you can use it with confidence :)\nconsole.log(data.name);\n```\n\n\n\n## Features\n\n- Zero external dependencies\n- Works in Node.js and all modern browsers\n- Tiny: `2kb` core bundle (gzipped)\n- Immutable API: methods return a new instance\n- Concise interface\n- Works with TypeScript and plain JS\n- Built-in JSON Schema conversion\n- Extensive ecosystem\n\n\n\n## Installation\n\n```sh\nnpm install zod\n```\n\n\n\n## Basic usage\n\nBefore you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.\n\n```ts\nimport * as z from "zod";\n\nconst Player = z.object({\n  username: z.string(),\n  xp: z.number(),\n});\n```\n\n### Parsing data\n\nGiven any Zod schema, use `.parse` to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input.\n\n```ts\nPlayer.parse({ username: "billie", xp: 100 });\n// => returns { username: "billie", xp: 100 }\n```\n\n**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](https://zod.dev/api#refinements) or [transforms](https://zod.dev/api#transforms), you'll need to use the `.parseAsync()` method instead.\n\n```ts\nconst schema = z.string().refine(async (val) => val.length  "hello"\n```\n\n### AO

常见问题 (5)

故障排除
为什么 Zod safeParse 的 error.message 返回的是 JSON 对象,而不是验证错误消息?

在 Zod 4 中,error.message 是一个包含所有验证问题的 JSON 字符串,因为单个 ZodError 可以包含多个错误。要获取第一条人类可读的消息,请使用:

const parsedData = signupSchema.safeParse(req.body);

if (!parsedData.success) {
  const message = parsedData.error.issues[0]?.message;
  return errorResponse(res, 400, message);
}

要获取所有错误消息:

const messages = parsedData.error.issues.map(issue => issue.message);

要将整个错误格式化为可读文本,请使用:

z.prettifyError(parsedData.error);

来源 Issue #6646
故障排除
如何修复 Zod v4 中 `.refine()` 类型谓词不再收窄推断出的类型的问题?

Zod **v4.2.2**(PR #5575)恢复了对 .refine() 中类型谓词的支持。请先升级:

npm install zod@^4.2.2

你现有的 v3 写法应该可以再次收窄输出类型:

const mySchema = z.string().refine(
  (val): val is "specific-value" => checkExternalLogic(val)
);

type MyType = z.infer<typeof mySchema>; // "specific-value"

如果无法从更早的 v4 版本升级,可以使用 z.custom<T>() 进行简单的基于谓词的收窄:

const mySchema = z.custom<"specific-value">(
  (val) => typeof val === "string" && checkExternalLogic(val),
  { message: "Expected specific-value" }
);

请注意,z.custom() 不会接收校验 ctx,因此无法添加多个自定义 issues。对于旧版 v4 上的自定义错误报告,请使用 .check() 或 .transform() 及其 context API,并显式地断言/收窄输出类型。首选的修复方案是升级到 Zod 4.2.2 或更高版本。

来源 Issue #5528
故障排除
如何修复在使用 Zod 和 TypeScript 7.1 nightly 时由 `.catchall(z.json())` 引发的 TS5115 'infinitely circular' 错误?

将 Zod 升级到包含 PR #6645 的版本(运行 npm install zod@latest 或 yarn add zod@latest)。该错误影响使用 TypeScript 7.1 开发构建版本的 Zod 4.5.4 和 4.6.5;TypeScript 7.0.2 不受影响。如果无法立即升级,可以继续使用 TypeScript 7.0.2,或者修补 v4/core/schemas.d.ts 和 .d.cts 中的 $ZodRecordInternals,使其不带类型参数地扩展 $ZodTypeInternals,并直接声明 output 和 input:

export interface $ZodRecordInternals<
  Key extends $ZodRecordKey = $ZodRecordKey,
  Value extends SomeType = $ZodType,
> extends $ZodTypeInternals {
  def: $ZodRecordDef<Key, Value>;
  isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
  optin?: "optional" | undefined;
  optout?: "optional" | undefined;
  output: $InferZodRecordOutput<Key, Value>;
  input: $InferZodRecordInput<Key, Value>;
}

来源 Issue #6637
故障排除
为什么在 esbuild 中 `import { z } from 'zod'` 的体积比 `import * as z` 大 4–5 倍,以及如何减小 Zod v4 的打包体积?

这会影响 Zod v4(使用 zod@4.6.4 和 esbuild@0.28.2 复现)。Zod 以 export { z, z as default } 的形式导出该命名空间。Rollup 和 Webpack 可以对这个重导出进行 tree-shake,但 esbuild 会将重导出的命名空间对象视为不透明,因此 import { z } from 'zod' 和默认导入都会保留约 736 KB。请直接使用命名空间导入:

import * as z from 'zod';
z.object({ x: z.string() });

在复现示例中,这将输出体积从 736 KB 降至约 165 KB。使用 esbuild 时请避免以下形式:

import { z } from 'zod';
import z from 'zod';

细粒度的函数导入也可以被 tree-shake:

import { object, string } from 'zod';
object({ x: string() });

如果某个第三方依赖(例如 @tanstack/ai)内部使用了 import { z } from 'zod',请使用 patch-package 修补该依赖(或维护一个 fork/resolution),将其改为 import * as z from 'zod'。使用 Rollup 的 Vite 生产构建不会受到同样的影响;这种差异主要出现在由 esbuild 执行打包时,例如直接使用 esbuild 或 Vite 的开发服务器。请使用 metafile 验证结果:

npx esbuild app.ts --bundle --platform=node --format=esm --outfile=out.mjs --metafile=meta.json

来源 Issue #6597
故障排除
为什么我的穷举式 Zod v4 访问器会遗漏 $ZodFunction 和 $ZodPrefault?

核心文档在已记录的 $ZodTypes 联合类型中错误地遗漏了这些成员。packages/zod/src/v4/core/schemas.ts 中的权威定义同时包含 $ZodFunction 和 $ZodPrefault。请更新穷举式访问器或类型级 switch 以处理 $ZodFunction 和 $ZodPrefault,或者从源码中的 $ZodTypes 派生你的分支,而不是复制文档中的联合类型。该文档修复在 packages/docs/content/packages/core.mdx 中将这两个类型添加到 $ZodTypes,并将 $ZodFunction 添加到继承关系图中。

来源 Issue #6631