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

版本控制

更新 — 2025 年 7 月 8 日

[email protected] 已經發布到 npm。包根目錄("zod")現在導出 Zod 4。所有其他子路徑都沒有改變,並將永遠保持可用。

要升級到 Zod 4:

npm install zod@^4.0.0

如果您正在使用 Zod 4,您現有的導入("zod/v4""zod/v4-mini")將繼續永遠工作。但是,升級後,您可以 選擇性地 重寫您的導入如下:

BeforeAfter
Zod 4"zod/v4""zod"
Zod 4 Mini"zod/v4-mini""zod/mini"
Zod 3"zod""zod/v3"

庫作者 — 如果您已經根據 庫作者 指南中概述的最佳實踐實現了 Zod 4 支持,請將您的對等依賴項版本提升以包含 zod@^4.0.0

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

應該不需要其他代碼更改。 在最新的 3.25.x 版本和 4.0.0 之間沒有進行代碼更改。這不需要主要的版本升級。

關於子路徑版本控制的一些說明

最終,子路徑版本控制方案是迫使生態系統以非破壞性方式升級的必要之惡。如果我一開始就發布了 [email protected],大多數庫會天真地升級他們的對等依賴項,迫使整個生態系統發生「版本升級雪崩」。

目前,整個生態系統對 Zod 4 已經有了 廣泛的支持。沒有任何遷移過程是完全無痛的,但我擔心的「版本雪崩」似乎並沒有發生。總的來說,庫已經能夠同時支持 Zod 3 和 Zod 4:Hono、LangChain、React Hook Form 等。幾位生態系統維護者專門聯繫我,表示逐步添加對 Zod 4 的支持是多麼方便(這通常需要主要的版本升級)。長話短說:這種方法效果很好!很少有其他庫受到與 Zod 相同的限制,但我強烈建議其他擁有龐大關聯生態系統的庫考慮採取類似的方法。

Zod 4 中的版本控制

這是對 Zod 4 版本控制方法的記錄,旨在讓用戶和 Zod 的關聯庫生態系統更容易遷移到 Zod 4。

總體方法:

  • Zod 4 最初不會在 npm 上以 [email protected] 發布。相反,它將在子路徑("zod/v4")與 [email protected] 一起導出
  • 儘管如此,Zod 4 被認為是穩定和生產就緒的
  • Zod 3 將繼續從包根目錄("zod")以及新的子路徑 "zod/v3" 導出。它將繼續接收錯誤修復和穩定性改進。

這種方法類似於 Golang 處理主要版本更改的方式:https://go.dev/doc/modules/major-version

一段時間後:

  • 包根目錄("zod")將從導出 Zod 3 切換到 Zod 4
  • 此時 [email protected] 將發布到 npm
  • "zod/v4" 子路徑將永遠保持可用

為什麼?

Zod 在生態系統中佔據獨特的位置。生態系統中的許多庫/框架接受用戶定義的 Zod 架構。這意味著它們的面向用戶的 API 與 Zod 及其各種類/接口/實用程序緊密耦合。對於這些庫/框架,對 Zod 的破壞性更改必然會導致對其用戶的破壞性更改。Zod 3 的 ZodType 不能分配給 Zod 4 的 ZodType

為什麼庫不能同時支持 v3 和 v4?

遺憾的是,peerDependencies 的局限性(以及包管理器之間的不一致)使得優雅地同時支持一個庫的兩個主要版本變得極其困難。

如果我天真地將 [email protected] 發布到 npm,Zod 生態系統中的絕大多數庫都需要發布一個新的主要版本來正確支持 Zod 4,包括像 AI SDK 這樣的高知名度庫。這將在整個生態系統中引發「版本升級雪崩」,並普遍造成巨大的挫敗感和工作量。

通過子路徑版本控制,我們解決了這個問題。它為庫同時支持 Zod 3 和 Zod 4(包括 Zod Mini)提供了一種直接的方法。它們可以繼續在 "zod" 上定義單個 peerDependency;不需要像 npm 別名、可選對等依賴項、"zod-compat" 包或其他此類黑客手段那樣的晦澀解決方案。

庫需要將其 "zod" 對等依賴項的最低版本提升到 zod@^3.25.0。然後它們可以在實現中同時引用 Zod 3 和 Zod 4:

import * as z3 from "zod/v3"
import * as z4 from "zod/v4"

稍後,一旦對 v4 有了廣泛的支持,我們將在 npm 上提升主要版本,並開始從包根目錄導出 Zod 4,完成過渡。(這已經發生了——請參閱本頁頂部的說明。)

只要庫專門從相關的子路徑(而不是根目錄)導入,它們的實現將在主要版本升級中繼續工作,無需更改代碼。

雖然這看起來可能有些非正統(至少對於不使用 Go 的人來說!),但這是我所知道的唯一一種能夠為 Zod 的用戶和更廣泛生態系統中的庫提供清晰、增量遷移路徑的方法。


更深入地探討為什麼對等依賴項在這種情況下不起作用。

想像一下,您是一個試圖構建接受 Zod 架構的函數 acceptSchema 的庫。您希望能夠接受 Zod 3 或 Zod 4 架構。在這個假設中,我想像 Zod 4 以 zod@4 發布在 npm 上,沒有子路徑。您的選項如下:

  1. 使用 npm 別名同時安裝 zod@3 和 zod@4 作為 dependencies。這行得通,但最終您會包含 Zod 3 和 Zod 4 的副本。您無法保證用戶的 Zod 架構是您從依賴項中拉取的同一個 z.ZodType 類的實例(instanceof 檢查可能會失敗)。

  2. 使用跨越多個主要版本的對等依賴項:"zod@>=3.0.0" ……但在開發庫時,您仍然需要選擇一個版本進行開發。通常您會將其安裝為開發依賴項。您有責任費力地確保您的代碼在兩個版本中都能逐字逐句地工作。在 Zod 3 和 Zod 4 的情況下,這是不可能的,因為許多非常基本的類都簡化/更改了泛型。

  3. 可選的對等依賴項。我只是找不到關於如何在所有平台上運行時可靠地確定安裝了哪個對等依賴項的直接答案。網上的許多答案會說「在 try/catch 中使用動態導入來檢查包是否存在」。這些人假設您在後端,因為前端打包器對此沒有提供支持。當您嘗試打包未安裝的依賴項時,它們會失敗。顯然,如果在構建步驟中的 try/catch 內部,這並不重要。此外:因為我們談論的是同一個庫的多個版本,所以您需要使用 npm 別名在 package.json 中區分這兩個版本。像 v10 這樣新的 npm 版本無法處理對等依賴項 + npm 別名的組合。

  4. zod-compat。您在網上看到的這種極其模糊的解決方案是「為每個代表某些基本功能的版本定義接口」。基本上是一些實用程序類型庫可以用來近似真實的東西。這很容易出錯,工作量很大,需要與實際實現保持同步,最終庫是針對可能缺乏細節的庫的影子版本進行開發的。它也僅適用於類型:如果庫依賴於 Zod 中的任何運行時代碼,它就會崩潰。

因此,子路徑。

On this page