💎 Zod 4 is now stable!  Read the announcement.
Zod logo

致庫作者 (For library authors)

更新 — 2025 年 7 月 10 日

Zod 4.0.0 已在 npm 上發佈。這完成了下面描述的增量推出過程。要添加支持,請更新您的對等依賴項以包含 zod@^4.0.0

// package.json
{
  "peerDependencies": {
    "zod": "^3.25.0 || ^4.0.0"
  }
}

如果您已經根據下面描述的最佳實踐(例如使用 "zod/v4/core" 子路徑)實​​現了 Zod 4 支持,那麼不需要更改其他代碼。這不應要求您的庫進行主要版本升級。

本頁面主要供在 Zod 之上構建工具的 庫作者 閱讀。

如果您在 Zod 之上構建庫並認為此頁面應包含一些額外的指南,請開啟一個 issue!

我需要依賴 Zod 嗎? (Do I need to depend on Zod?)

首先,請確保您根本需要依賴 Zod。

如果您正在構建一個接受用戶定義的架構來執行黑盒驗證的庫,則可能不需要專門與 Zod 集成。相反,請查看 Standard Schema。這是 TypeScript 生態系統中大多數流行驗證庫(見 完整列表)實現的共享接口,包括 Zod。

如果您接受用戶定義的架構並將其視為「黑盒」驗證器,則此規範非常有效。給定任何兼容的庫,您可以提取推斷的輸入/輸出類型,驗證輸入並獲得標準化錯誤。

如果您需要 Zod 特定的功能,請繼續閱讀。

如何配置對等依賴項? (How to configure peer dependencies?)

任何構建在 Zod 之上的庫都應在 "peerDependencies" 中包含 "zod"。這讓您的用戶「自帶 Zod」。

// package.json
{
  // ...
  "peerDependencies": {
    "zod": "^3.25.0 || ^4.0.0" // the "zod/v4" subpath was added in 3.25.0
  }
}

在開發過程中,您需要滿足自己的對等依賴項要求,為此,請將 "zod" 也添加到您的 "devDependencies" 中。

// package.json
{
  "peerDependencies": {
    "zod": "^3.25.0 || ^4.0.0"
  },
  "devDependencies": {
    // generally, you should develop against the latest version of Zod
    "zod": "^3.25.0 || ^4.0.0"
  }
}

如何支持 Zod 4? (How to support Zod 4?)

要支持 Zod 4,請將您的 "zod" 對等依賴項的最低版本更新為 ^3.25.0 || ^4.0.0

// package.json
{
  // ...
  "peerDependencies": {
    "zod": "^3.25.0 || ^4.0.0"
  }
}

v3.25.0 開始,Zod 4 核心包可在 "zod/v4/core" 子路徑中獲得。請閱讀 Zod 4 中的版本控制 文章,以瞭解此版本控制方法的完整背景。

import * as z4 from "zod/v4/core";

僅從這些子路徑導入。將它們視為指向其各自 Zod 版本的「永久鏈接」。這些將永遠可用。

  • "zod/v3" 用於 Zod 3 ✅
  • "zod/v4/core" 用於 Zod 4 Core 包 ✅

您通常不應從任何其他路徑導入。Zod Core 庫是一個共享庫,它是 Zod 4 Classic 和 Zod 4 Mini 的基礎。實現特定於其中一個的功能通常是一個壞主意。不要從這些子路徑導入:

  • "zod" — ❌ 在 3.x 版本中,這導出 Zod 3。在 4.x 版本中,這將導出 Zod 4。請改用永久鏈接。
  • "zod/v4""zod/v4/mini"— ❌ 這些子路徑分別是 Zod 4 Classic 和 Mini 的主頁。如果您希望您的庫同時與 Zod 和 Zod Mini 兼容,則應針對 "zod/v4/core" 中定義的基類進行構建。如果您引用 "zod/v4" 模塊中的類,您的庫將與 Zod Mini 不兼容,反之亦然。極不推薦這樣做。請改用 "zod/v4/core",它導出由 Zod Classic 和 Zod Mini 擴展的以 $ 為前綴的子類。Classic 和 Mini 子類的內部結構是相同的;它們僅在其實現的輔助方法上有所不同。

我需要發佈新的主要版本嗎? (Do I need to publish a new major version?)

不,您不需要發佈庫的新主要版本來支持 Zod 4(除非您要放棄對 Zod 3 的支持,這不推薦)。

您需要將對等依賴項升級到 ^3.25.0,因此您的用戶將需要 npm upgrade zod。但是在 [email protected][email protected] 之間沒有對 Zod 3 進行重大更改;事實上,根本沒有代碼更改。由於您的用戶需要更改代碼,我不認為這構成重大更改。我建議不要發佈新的主要版本。

如何同時支持 Zod 3 和 Zod 4? (How to support Zod 3 and Zod 4 simultaneously?)

v3.25.0 開始,該包包含 Zod 3 和 Zod 4 的副本,分別位於其各自的子路徑中。這使得同時支持兩個版本變得容易。

import * as z3 from "zod/v3";
import * as z4 from "zod/v4/core";
 
type Schema = z3.ZodTypeAny | z4.$ZodType;
 
function acceptUserSchema(schema: z3.ZodTypeAny | z4.$ZodType) {
  // ...
}

要在運行時區分 Zod 3 和 Zod 4 架構,請檢查 "_zod" 屬性。此屬性僅在 Zod 4 架構上定義。

import type * as z3 from "zod/v3";
import type * as z4 from "zod/v4/core";
 
declare const schema: z3.ZodTypeAny | z4.$ZodType;
 
if ("_zod" in schema) {
  schema._zod.def; // Zod 4 schema
} else {
  schema._def; // Zod 3 schema
}

如何同時支持 Zod 和 Zod Mini? (How to support Zod and Zod Mini simultaneously?)

您的庫代碼應僅從 "zod/v4/core" 導入。此子包定義了 Zod 和 Zod Mini 之間共享的接口、類和實用程序。

// library code
import * as z4 from "zod/v4/core";
 
export function acceptObjectSchema<T extends z4.$ZodObject>(schema: T){
  // parse data
  z4.parse(schema, { /* somedata */});
  // inspect internals
  schema._zod.def.shape;
}

通過針對共享的基本接口進行構建,您可以可靠地同時支持這兩個子包。此函數可以同時接受 Zod 和 Zod Mini 架構。

// user code
import { acceptObjectSchema } from "your-library";
 
// Zod 4
import * as z from "zod";
acceptObjectSchema(z.object({ name: z.string() }));
 
// Zod 4 Mini
import * as zm from "zod/mini";
acceptObjectSchema(zm.object({ name: zm.string() }))

有關核心子庫內容的更多信息,請參閱 Zod Core 頁面。

如何接受用戶定義的架構? (How to accept user-defined schemas?)

接受用戶定義的架構是任何構建在 Zod 上的庫的基本操作。本節概述了這樣做的最佳實踐。

剛開始時,編寫一個像這樣接受 Zod 架構的函數可能很誘人:

import * as z4 from "zod/v4/core";
 
function inferSchema<T>(schema: z4.$ZodType<T>) {
  return schema;
}

這種方法是不正確的,並且限制了 TypeScript 正確推斷參數的能力。無論您傳入什麼,schema 的類型都將是 $ZodType 的實例。

inferSchema(z.string());
// => $ZodType<string>

這種方法丟失了類型信息,即輸入實際是 哪個子類(在本例中為 ZodString)。這意味著您無法在 inferSchema 的結果上調用任何特定於字串的方法(如 .min())。相反,您的泛型參數應擴展核心 Zod 架構接口:

function inferSchema<T extends z4.$ZodType>(schema: T) {
  return schema;
}
 
inferSchema(z.string());
// => ZodString ✅

要將輸入架構限制為特定子類:

 
import * as z4 from "zod/v4/core";
 
// only accepts object schemas
function inferSchema<T>(schema: z4.$ZodObject) {
  return schema;
}

要限制輸入架構的推斷輸出類型:

 
import * as z4 from "zod/v4/core";
 
// only accepts string schemas
function inferSchema<T extends z4.$ZodType<string>>(schema: T) {
  return schema;
}
 
inferSchema(z.string()); // ✅ 
 
inferSchema(z.number()); 
// ❌ The types of '_zod.output' are incompatible between these types. 
// // Type 'number' is not assignable to type 'string'

要使用架構解析數據,請使用頂級 z4.parse/z4.safeParse/z4.parseAsync/z4.safeParseAsync 函數。z4.$ZodType 子類本身沒有方法。通常的解析方法由 Zod 和 Zod Mini 實現,但在 Zod Core 中不可用。

function parseData<T extends z4.$ZodType>(data: unknown, schema: T): z4.output<T> {
  return z.parse(schema, data);
}
 
parseData("sup", z.string());
// => string