Ahmed Mahmoud

標題: Zod 4 是 TypeScript-first 的 schema 驗證函式庫的重寫版本,於 2025 年以穩定主要版本發布。四項變更直接影響到我的程式碼:字串格式移至頂層函式(使用 z.email() 取代 z.string().email())、四種錯誤選項合併為單一 error 參數、錯誤格式化移至獨立的輔助函式(z.flattenErrorz.treeifyErrorz.prettifyError),以及 .strict()/.passthrough() 改為 z.strictObject()/z.looseObject()。已棄用的 Zod 3 API 仍可運作但會顯示警告,因此我採用漸進式遷移。

重點摘要

  • Zod 4 是 TypeScript-first 的 schema 驗證函式庫的穩定主要版本,於 2025 年發布;需要 TypeScript 5.5 或更新版本。
  • 字串格式現已改為頂層可 tree-shake 的函式 — z.email()z.uuid()z.url() — 且 z.string().email() 已棄用但仍可使用。
  • 單一 error 參數取代 Zod 3 的 messageinvalid_type_errorrequired_errorerrorMap
  • 錯誤格式化移至 z.flattenError(表單欄位)、z.treeifyError(巢狀結構)及 z.prettifyError(人類可讀字串)。
  • zod/mini 建置版透過函式式、可 tree-shake 的 API 提供相同驗證器;z.infer.parse().safeParse() 並未改變。

幾乎在每個專案中,我都會使用 Zod 來驗證邊界處不受信任的輸入 — 例如請求主體、表單資料、環境變數、API 回應。Zod 4 改變了足夠多的表面 API,導致機械式升級影響了少數檔案,因此我精確地記錄了哪些部分發生了變動。

Zod 4 究竟改變了什麼?

Zod 4 是 TypeScript-first 的 schema 驗證函式庫的全面重寫版本,於 2025 年以穩定主要版本發布。重點在於效能:Zod 團隊的發布說明指出,TypeScript 編譯器實例化大幅減少,且執行時解析速度更快,這對於 schema 類型主導型別檢查時間的大型程式碼庫來說特別重要。四項 API 變更直接影響到我的程式碼 — 字串格式移至頂層函式、四種錯誤選項合併為一、錯誤格式化移至獨立輔助函式,以及 .strict()/.passthrough() 改為 z.strictObject()/z.looseObject()

為什麼 z.string().email() 變成 z.email()?

Zod 4 將字串格式提升為獨立的頂層函式 — z.email()z.uuid()z.url(),以及 z.iso 下的 ISO 輔助函式 — 而非鏈接在 z.string() 上的方法。鏈接形式仍可運作,但已棄用並會發出警告。原因是 tree-shaking:每種格式都是獨立的函式,因此僅驗證電子郵件的 bundle 不再需要包含其他所有格式的邏輯。

import * as z from "zod";

const User = z.object({
  id: z.uuid(),
  email: z.email(),
  website: z.url().optional(),
  age: z.number().int().min(18),
});

type User = z.infer<typeof User>;

Enter fullscreen mode Exit fullscreen mode

在 Zod 4 中如何設定自訂錯誤訊息?

Zod 4 以單一 error 參數取代四種獨立的錯誤選項。在 Zod 3 中,你可以傳遞 messageinvalid_type_errorrequired_error 或完整的 errorMap。在 Zod 4 中,你只需傳遞一個 error:字串代表固定訊息,或接收 issue 並回傳訊息的函式,讓你能在同一個地方區分缺少值與錯誤型別。

// Zod 4: one error param — string or function
z.string({ error: "Name is required" });

z.string({
  error: (issue) =>
    issue.input === undefined ? "Name is required" : "Name must be text",
});

Enter fullscreen mode Exit fullscreen mode

如何將 ZodError 轉換為表單錯誤?

Zod 4 將錯誤格式化移至三個頂層輔助函式。z.flattenError(error) 會回傳 { formErrors, fieldErrors },可對應到表單的欄位層級訊息。z.treeifyError(error) 會回傳與 schema 形狀相符的巢狀物件。z.prettifyError(error) 會回傳供日誌使用的人類可讀多行字串。原始的 error.issues 陣列維持不變;error.format()error.flatten() 已棄用,請改用這些輔助函式。

const result = User.safeParse(await request.json());

if (!result.success) {
  const { fieldErrors } = z.flattenError(result.error);
  return Response.json({ errors: fieldErrors }, { status: 400 });
}

const user = result.data; // fully typed as User

Enter fullscreen mode Exit fullscreen mode

何時應該使用 zod/mini 而非完整的 zod 套件?

當 bundle 大小很重要時(例如用戶端程式碼、edge functions、已發布的小工具),請使用 zod/mini;其他情況則使用完整的 zod 套件。zod/mini 透過函式式 API 提供相同驗證器:取代鏈接 .optional(),你需要使用 z.optional() 包裝,而 refinements 則使用 .check() 而非 .refine()。雖然較為冗長,但由於沒有方法鏈,未使用的程式碼可以被 tree-shake 移除。兩種建置版共用相同核心,因此執行時行為完全相同。

import * as z from "zod/mini";

const User = z.object({
  email: z.email(),
  name: z.optional(z.string()),
});

Enter fullscreen mode Exit fullscreen mode

考量點 zod(完整版) zod/mini
API 風格 鏈接方法(.optional() 函式包裝器(z.optional()
Bundle 大小 較大 較小、可 tree-shake
易用性 流暢、易讀 較為冗長
驗證器相同 是(相同核心)
最適合用於 伺服器、一般程式碼 Edge/用戶端、對大小敏感的 bundle

如何從 Zod 3 遷移而不破壞一切?

採用漸進式遷移,因為 Zod 4 保留已棄用的 Zod 3 API(會顯示警告而非移除)。在過渡期間,Zod 將新版本以 zod/v4 匯入路徑發布(在 [email protected] 中),讓你可以在 [email protected] 發布前逐檔採用;舊版 API 仍可透過 zod/v3 存取。我的流程是:升級套件、執行型別檢查與測試,然後分批清除棄用警告 — 重新命名字串格式呼叫、將錯誤選項合併為 error,以及將 .strict()/.passthrough() 切換至新的物件函式。z.infer.parse().safeParse() 並未改變,因此大多數 schema 仍可正常運作。

常見問答

Q: z.string().email() 在 Zod 4 中已被移除嗎?
A: 沒有。它仍可運作,但已棄用並會顯示警告。建議的形式是頂層的 z.email(),兩者驗證結果相同。

Q: 在 Zod 4 中,什麼取代了 errorMap 與 invalid_type_error?
A: 單一 error 參數 — 字串代表固定訊息,或接收 issue 並回傳條件式訊息的函式。

Q: 在 Zod 4 中如何取得表單的欄位層級錯誤?
A: 呼叫 z.flattenError(error);其 fieldErrors 會將每個 schema 鍵對應到其訊息。若為巢狀形狀,請使用 z.treeifyError

Q: zod/mini 是獨立的函式庫嗎?
A: 不是。它是 Zod 4 的建置版,透過函式式、可 tree-shake 的 API 提供相同驗證器,以取得更小的 bundle。

Q: Zod 4 是否需要特定版本的 TypeScript?
A: 是的。Zod 4 需要 TypeScript 5.5 或更新版本。


Originally published on devya.dev. Also on eng-ahmed.com. Built by Devya Solutions.