定義架構
要驗證數據,您必須首先定義一個 架構。架構代表 類型,從簡單的原始值到復雜的嵌套對象和數組。
原始類型
強制轉換 (Coercion)
要將輸入數據強制轉換為適當的類型,請改用 z.coerce:
這些架構的強制轉換變體嘗試將輸入值轉換為適當的類型。
默認情況下,這些強制轉換架構的輸入類型是 unknown。要指定更具體的輸入類型,請傳遞一個泛型參數:
字面量 (Literals)
字面量架構代表 字面量類型,如 "hello world" 或 5。
要表示 JavaScript 字面量 null 和 undefined:
允許使用多個字面量值:
要從字面量架構中提取允許值的集合:
字串 (Strings)
Zod 提供了一些內置的字串驗證和轉換 API。要執行一些常見的字串驗證:
要執行一些簡單的字串轉換:
字串格式 (String formats)
要驗證一些常見的字串格式:
電子郵件 (Emails)
要驗證電子郵件地址:
默認情況下,Zod 使用相對嚴格的電子郵件正則表達式,旨在驗證包含常見字符的普通電子郵件地址。它大致相當於 Gmail 強制執行的規則。要了解有關此正則表達式的更多信息,請參閱 這篇文章。
要自定義電子郵件驗證行為,您可以將自定義正則表達式傳遞給 pattern 參數。
Zod 導出了幾個您可能有用的正則表達式。
UUIDs
要驗證 UUID:
要指定特定的 UUID 版本:
RFC 9562/4122 UUID 規範要求第 8 個字節的前兩位為 10。其他類似 UUID 的標識符不強制執行此約束。要驗證任何類似 UUID 的標識符:
URLs
要驗證任何兼容 WHATWG 的 URL:
正如你所看到的,這是相當寬鬆的。在內部,它使用 new URL() 構造函數來驗證輸入;這種行為可能因平台和運行時而異,但它是驗證任何給定 JS 運行時/引擎上的 URI/URL 的最嚴格方法。
要針對特定正則表達式驗證主機名:
要針對特定正則表達式驗證協議,請使用 protocol 參數。
Web URLs — 在許多情況下,您會希望專門驗證 Web URL。這是推薦的架構:
這將協議限制為 http/https,並確保主機名是用於 z.regexes.domain 正則表達式的有效域名:
要規範化 URL,請使用 normalize 標誌。這將用 new URL() 返回的 規範化 URL 覆蓋輸入值。
ISO 日期時間 (ISO datetimes)
您可能已經注意到,Zod 字串包含一些與日期/時間相關的驗證。這些驗證是基於正則表達式的,因此它們不如完整的日期/時間庫嚴格。但是,它們對於驗證用戶輸入非常方便。
z.iso.datetime() 方法強制執行 ISO 8601;默認情況下,不允許時區偏移:
要允許時區偏移:
要允許不合格(無時區)的日期時間:
要限制允許的時間 precision(精度)。默認情況下,秒數是可選的,並且允許任意亞秒精度。
ISO 日期 (ISO dates)
z.iso.date() 方法驗證格式為 YYYY-MM-DD 的字串。
ISO 時間 (ISO times)
z.iso.time() 方法驗證格式為 HH:MM[:SS[.s+]] 的字串。默認情況下秒數是可選的,亞秒小數也是如此。
不允許任何類型的偏移量。
使用 precision 參數限制允許的小數精度。
IP 地址 (IP addresses)
IP 塊 (CIDR)
使用 CIDR 表示法 驗證 IP 地址範圍。
MAC 地址 (MAC Addresses)
驗證標準 48 位 MAC 地址 IEEE 802。
JWTs
驗證 JSON Web Tokens。
哈希 (Hashes)
要驗證加密哈希值:
默認情況下,z.hash() 像往常一樣期望十六進制編碼。您可以使用 enc 參數指定不同的編碼:
自定義格式 (Custom formats)
要定義您自己的字串格式:
此架構將產生 "invalid_format" 問題,這比細化或 z.custom() 產生的 "custom" 錯誤更具描述性。
模板字串 (Template literals)
New — 在 [email protected] 中引入。
要定義模板字串架構:
z.templateLiteral API 可以處理任意數量的字串字面量(例如 "hello")和架構。可以傳遞任何推斷類型可分配給 string | number | bigint | boolean | null | undefined 的架構。
數字 (Numbers)
使用 z.number() 驗證數字。它允許任何有限數字。
Zod 實現了一些特定於數字的驗證:
如果(由於某種原因)您想驗證 NaN,請使用 z.nan()。
整數 (Integers)
要驗證整數:
BigInts
要驗證 BigInts:
Zod 包含一些特定於 bigint 的驗證。
布爾值 (Booleans)
要驗證布爾值:
日期 (Dates)
使用 z.date() 驗證 Date 實例。
要自定義錯誤消息:
Zod 提供了一些特定於日期的驗證。
枚舉 (Enums)
使用 z.enum 針對一組固定的允許 字串 值驗證輸入。
支持類似枚舉的對象字面量 ({ [key: string]: string | number })。
您還可以傳入外部聲明的 TypeScript 枚舉。
Zod 4 — 這取代了 Zod 3 中的 z.nativeEnum() API。
注意,不推薦 使用 TypeScript 的 enum 關鍵字。
.enum
要將架構的值提取為類似枚舉的對象:
.exclude()
要創建一個新的枚舉架構,排除某些值:
.extract()
要創建一個新的枚舉架構,提取某些值:
布爾字串 (Stringbools)
💎 Zod 4 新功能
在某些情況下(例如解析環境變量),將某些字串「布爾」值解析為純 boolean 值很有價值。為了支持這一點,Zod 4 引入了 z.stringbool():
要自定義真值和假值:
默認情況下,該架構是 不區分大小寫 的;在與 truthy/falsy 值進行比較之前,所有輸入都會轉換為小寫。要使其區分大小寫:
可選 (Optionals)
要使架構 可選(即允許 undefined 輸入)。
這將返回一個包裝原始架構的 ZodOptional 實例。要提取內部架構:
可空 (Nullables)
要使架構 可空(即允許 null 輸入)。
這將返回一個包裝原始架構的 ZodNullable 實例。要提取內部架構:
可空可選 (Nullish)
要使架構 可空可選(即既可選又可空):
有關 nullish 概念的更多信息,請參閱 TypeScript 手冊。
Unknown
Zod 旨在與 TypeScript 的類型系統一一對應。因此,Zod 提供了用於表示以下特殊類型的 API:
Never
任何值都不會通過驗證。
對象 (Objects)
要定義對象類型:
默認情況下,所有屬性都是必需的。要使某些屬性可選:
默認情況下,無法識別的鍵會從解析結果中 剝離:
z.strictObject
定義一個 嚴格 架構,當發現未知鍵時拋出錯誤:
z.looseObject
定義一個 寬鬆 架構,允許未知鍵通過:
.catchall()
定義一個 捕獲所有架構,用於驗證任何無法識別的鍵:
.shape
要訪問內部架構:
.keyof()
從對象架構的鍵創建 ZodEnum 架構:
.extend()
要向對象架構添加其他字段:
此 API 可用於覆蓋現有字段!請小心使用這種能力!如果兩個架構共享鍵,B 將覆蓋 A。
替代方案:展開語法 — 您也可以通過完全創建一個新的對象架構來完全避免 .extend()。這使得結果架構的嚴格性級別在視覺上顯而易見。
您也可以使用它一次合併多個對象。
這種方法有幾個優點:
- 使用語言級功能(展開語法)而不是庫特定的 API
- 在 Zod 和 Zod Mini 中使用相同的語法
- 它更
tsc高效——.extend()方法在大型架構上可能很昂貴,而且由於 TypeScript 限制,當鏈接調用時,它會變得非常昂貴 - 如果您願意,您可以使用
z.strictObject()或z.looseObject()更改結果架構的嚴格性級別
.safeExtend()
.safeExtend() 方法與 .extend() 類似,但它不允許您用不可分配的架構覆蓋現有屬性。換句話說,.safeExtend() 的結果將具有一個推斷類型,該類型 extends 原始類型(在 TypeScript 意義上)。
使用 .safeExtend() 擴展包含細化的架構。(在包含細化的架構上使用常規 .extend() 會拋出錯誤。)
.pick()
受 TypeScript 內置的 Pick 和 Omit 實用程序類型的啟發,Zod 提供了用於從對象架構中選取和省略某些鍵的專用 API。
從這個初始架構開始:
要選取某些鍵:
.omit()
要省略某些鍵:
.partial()
為了方便起見,Zod 提供了一個專用 API,用於使部分或所有屬性可選,其靈感來自內置的 TypeScript 實用程序類型 Partial。
要使所有字段可選:
要使某些屬性可選:
.required()
Zod 提供了一個 API,用於使部分或所有屬性 必需,其靈感來自 TypeScript 的 Required 實用程序類型。
要使所有屬性必需:
要使某些屬性必需:
遞歸對象 (Recursive objects)
要定義自引用類型,請在鍵上使用 getter。這讓 JavaScript 在運行時解析循環架構。
雖然支持遞歸架構,但將循環數據傳入 Zod 會導致無限循環。
您也可以表示 相互遞歸類型:
所有對象 API(.pick()、.omit()、.required()、.partial() 等)都按預期工作。
循環錯誤 (Circularity errors)
由於 TypeScript 的限制,遞歸類型推斷可能很挑剔,並且僅在某些情況下有效。一些更復雜的類型可能會觸發遞歸類型錯誤,如下所示:
在這些情況下,您可以通過在違規的 getter 上添加類型註釋來解決錯誤:
數組 (Arrays)
要定義數組架構:
訪問數組元素的內部架構。
Zod 實現了一些特定於數組的驗證:
元組 (Tuples)
與數組不同,元組通常是固定長度的數組,為每個索引指定不同的架構。
要添加可變參數("rest")參數:
聯合 (Unions)
聯合類型 (A | B) 代表邏輯「或」。Zod 聯合架構將按順序根據每個選項檢查輸入。返回第一個驗證成功的值。
要提取內部選項架構:
判別聯合 (Discriminated unions)
判別聯合 是一種特殊的聯合,其中 a) 所有選項都是對象架構,且 b) 共享一個特定的鍵(「鑑別器」)。根據鑑別器鍵的值,TypeScript 能夠按預期「縮小」類型簽名。
您可以用常規的 z.union() 來表示它。但常規聯合是 天真 的——它們按順序根據每個選項檢查輸入,並返回第一個通過的選項。對於大型聯合來說,這可能很慢。
因此,Zod 提供了一個 z.discriminatedUnion() API,它使用 鑑別器鍵 來使解析更高效。
每個選項都應該是一個 對象架構,其鑑別器屬性(上例中的 status)對應於某個字面量值或值集,通常是 z.enum()、z.literal()、z.null() 或 z.undefined()。
交叉 (Intersections)
交叉類型 (A & B) 代表邏輯「與」。
這對於交叉兩個對象類型很有用。
合併對象架構時,優先使用 A.extend(B) 而不是交叉。使用 .extend() 會給您一個新的對象架構,而 z.intersection(A, B) 返回一個 ZodIntersection 實例,該實例缺少 pick 和 omit 等常用對象方法。
記錄 (Records)
記錄架構用於驗證 Record<string, string> 等類型。
鍵架構可以是任何可分配給 string | number | symbol 的 Zod 架構。
創建包含由枚舉定義的鍵的對象架構:
Zod 4 — 在 Zod 4 中,如果您將 z.enum 作為第一個參數傳遞給 z.record(),Zod 將詳盡地檢查所有枚舉值是否作為鍵存在於輸入中。此行為與 TypeScript 一致:
在 Zod 3 中,未檢查詳盡性。要複製舊行為,請使用 z.partialRecord()。
如果您想要一個 partial(部分)記錄類型,請使用 z.partialRecord()。這會跳過 Zod 通常使用 z.enum() 和 z.literal() 鍵架構運行的特殊詳盡性檢查。
Maps
Sets
可以使用以下實用程序方法進一步約束 Set 架構。
文件 (Files)
要驗證 File 實例:
Promises
已棄用 — z.promise() 在 Zod 4 中已棄用。Promise 架構的有效用例極少。如果您懷疑某個值可能是 Promise,只需在用 Zod 解析之前 await 它。
Instanceof
您可以使用 z.instanceof 來檢查輸入是否為類的實例。這對於驗證來自第三方庫的導出類很有用。
屬性 (Property)
要針對 Zod 架構驗證類實例的特定屬性:
z.property() API 適用於任何數據類型(但在與 z.instanceof() 結合使用時最有用)。
細化 (Refinements)
每個 Zod 架構都存儲一個 細化 數組。細化是一種執行 Zod 尚未提供本機 API 的自定義驗證的方法。
.refine()
細化函數不應拋出異常。相反,它們應該返回一個 falsy 值來表示失敗。拋出的錯誤不會被 Zod 捕獲。
error
要自定義錯誤消息:
abort
默認情況下,來自檢查的驗證問題被認為是 可繼續的;也就是說,Zod 將按順序執行 所有 檢查,即使其中一個導致驗證錯誤。這通常是可取的,因為這意味著 Zod 可以一次顯示儘可能多的錯誤。
要將特定細化標記為 不可繼續,請使用 abort 參數。如果檢查失敗,驗證將終止。
path
要自定義錯誤路徑,請使用 path 參數。這通常僅在對象架構的上下文中有用。
這將在關聯問題中設置 path 參數:
要定義異步細化,只需傳遞一個 async 函數:
如果您使用異步細化,則必須使用 .parseAsync 方法來解析數據!否則 Zod 會拋出錯誤。
when
注意 — 這是一個高級用戶功能,絕對可能被濫用,從而增加源自細化內部的未捕獲錯誤的可能性。
默認情況下,如果已經遇到任何 不可繼續 的問題,則細化不會運行。Zod 會在將值傳遞給任何細化函數之前,確保值的類型簽名是正確的。
在某些情況下,您希望更精細地控制細化何時運行。例如,考慮這個「密碼確認」檢查:
anotherField 上的錯誤將阻止執行密碼確認檢查,即使該檢查不依賴於 anotherField。要控制細化何時運行,請使用 when 參數:
.superRefine()
常規的 .refine API 僅生成一個帶有 "custom" 錯誤代碼的問題,但 .superRefine() 可以使用任何 Zod 的 內部問題類型 創建多個問題。
.check()
注意 — .check() API 是一個更低級的 API,通常比 .superRefine() 更複雜。在對性能敏感的代碼路徑中,它可能更快,但也更為冗長。
編解碼器 (Codecs)
New — 在 Zod 4.1 中引入。有關更多信息,請參閱專用的 編解碼器 頁面。
編解碼器是一種特殊的架構,它在其他兩個架構之間實現 雙向轉換。
常規的 .parse() 操作執行 前向轉換。它調用編解碼器的 decode 函數。
您也可以使用頂級 z.decode() 函數。與 .parse()(接受 unknown 輸入)不同,z.decode() 期望強類型的輸入(本例中為 string)。
要執行 反向轉換,請使用逆操作:z.encode()。
有關更多信息,請參閱專用的 編解碼器 頁面。該頁面包含常用編解碼器的實現,您可以將其複製/粘貼到您的項目中:
stringToNumberstringToIntstringToBigIntnumberToBigIntisoDatetimeToDateepochSecondsToDateepochMillisToDatejsonCodecutf8ToBytesbytesToUtf8base64ToBytesbase64urlToByteshexToBytesstringToURLstringToHttpURLuriComponentstringToBoolean
管道 (Pipes)
架構可以鏈接在一起形成「管道」。管道在與 轉換 結合使用時主要很有用。
轉換 (Transforms)
注意 — 對於雙向轉換,請使用 編解碼器。
轉換是一種特殊的架構,它執行單向轉換。它們不驗證輸入,而是接受任何內容並對數據執行某些轉換。要定義轉換:
轉換函數不應拋出異常。拋出的錯誤不會被 Zod 捕獲。
要在轉換內部執行驗證邏輯,請使用 ctx。要報告驗證問題,請將新問題推送到 ctx.issues(類似於 .check() API)。
最常見的是,轉換與 管道 結合使用。這種組合對於執行一些初始驗證,然後將解析後的數據轉換為另一種形式很有用。
.transform()
將一些架構通過管道傳輸到轉換是一種常見模式,因此 Zod 提供了一個方便的 .transform() 方法。
轉換也可以是異步的:
如果您使用異步轉換,則在解析數據時必須使用 .parseAsync 或 .safeParseAsync!否則 Zod 會拋出錯誤。
.preprocess()
將轉換通過管道傳輸到另一個架構是另一種常見模式,因此 Zod 提供了一個方便的 z.preprocess() 函數。
默認值 (Defaults)
要為架構設置默認值:
或者,您可以傳遞一個函數,該函數將在需要生成默認值時重新執行:
Prefaults
在 Zod 中,設置 default(默認)值將使解析過程短路。如果輸入是 undefined,則急切地返回默認值。因此,默認值必須可分配給架構的 輸出類型。
有時,定義 prefault(「預解析默認」)值很有用。如果輸入是 undefined,則將解析 prefault 值。解析過程 不 會短路。因此,prefault 值必須可分配給架構的 輸入類型。
如果您想將某些輸入值傳遞給一些變異細化,這也很有用。
捕獲 (Catch)
使用 .catch() 定義在發生驗證錯誤時返回的後備值:
或者,您可以傳遞一個函數,該函數將在需要生成捕獲值時重新執行。
品牌類型 (Branded types)
TypeScript 的類型系統是 結構化的,這意味著結構上等效的兩種類型被認為是相同的。
在某些情況下,在 TypeScript 內部模擬 名義類型 可能是可取的。這可以通過 品牌類型(也稱為「不透明類型」)來實現。
在後台,這是通過將「品牌」附加到架構的推斷類型來工作的。
有了這個品牌,任何普通(無品牌)數據結構都不再可分配給推斷類型。您必須使用架構解析一些數據以獲取品牌數據。
請注意,品牌類型不會影響 .parse 的運行時結果。這是一個僅靜態的構造。
只讀 (Readonly)
要將架構標記為只讀:
新架構的推斷類型將被標記為 readonly。請注意,在 TypeScript 中,這僅影響對象、數組、元組、 Set 和 Map:
輸入將像往常一樣被解析,然後結果將被 Object.freeze() 凍結以防止修改。
JSON
要驗證任何可 JSON 編碼的值:
這是一個方便的 API,它返回以下聯合架構:
函數 (Functions)
Zod 提供了一個 z.function() 實用程序,用於定義 Zod 驗證的函數。這樣,您可以避免將驗證代碼與業務邏輯混合。
函數架構有一個 .implement() 方法,它接受一個函數並返回一個自動驗證其輸入和輸出的新函數。
如果輸入無效,此函數將拋出 ZodError:
如果您只關心驗證輸入,可以省略 output 字段。
使用 .implementAsync() 方法創建異步函數。
自定義 (Custom)
您可以使用 z.custom() 為任何 TypeScript 類型創建 Zod 架構。這對於為 Zod 開箱即用不支持的類型(如模板字串字面量)創建架構很有用。
如果您不提供驗證函數,Zod 將允許任何值。這可能很危險!
您可以通過傳遞第二個參數來自定義錯誤消息和其他選項。此參數的工作方式與 .refine 的 params 參數相同。

