| name | zod |
| description | Zod v4 schema validation 最佳實踐指南。當需要定義 schema、驗證/解析 JSON 資料、type inference、或處理 unknown data 時使用。 |
Zod v4 Guide (v4.3+)
安裝
npm install zod
需要 TypeScript 5.5+ 且 "strict": true。
Import
import { z } from "zod";
Primitives
z.string() z.number() z.boolean()
z.null() z.undefined() z.unknown()
z.int() z.int32() z.float64()
Objects
const User = z.object({
name: z.string(),
age: z.number(),
});
const StrictUser = z.strictObject({ name: z.string() });
const LooseUser = z.looseObject({ name: z.string() });
Object 操作
User.extend({ email: z.email() });
z.object({ ...User.shape, email: z.email() });
User.pick({ name: true });
User.omit({ age: true });
User.partial();
User.required();
User.keyof();
Arrays
z.array(z.string())
z.array(z.string()).min(1).max(10)
Enums
const Color = z.enum(["red", "green", "blue"]);
enum Direction { Up, Down }
z.enum(Direction);
Optional / Nullable / Default
z.string().optional()
z.string().nullable()
z.string().nullish()
z.string().default("hi")
z.number().catch(0)
parse vs safeParse
const data = schema.parse(input);
const result = schema.safeParse(input);
if (result.success) {
result.data;
} else {
result.error;
}
Type Inference
type User = z.infer<typeof User>;
type UserInput = z.input<typeof User>;
最佳實踐:從 schema 推導 type(z.infer),不要另外定義 interface — single source of truth。
String Formats(v4 新增 top-level)
z.email() z.url() z.uuid()
z.iso.date() z.iso.datetime()
Transforms & Pipes
z.string().transform(val => val.length)
z.coerce.number()
Refinements
z.string().refine(val => val.length <= 255, { error: "Too long" });
z.object({
password: z.string(),
confirm: z.string(),
}).refine(d => d.password === d.confirm, {
error: "Passwords don't match",
path: ["confirm"],
});
Recursive Schemas(v4 用 getter,不需要 z.lazy)
const Category = z.object({
name: z.string(),
get children() { return z.array(Category); },
});
Branded Types
const UserId = z.string().brand<"UserId">();
type UserId = z.infer<typeof UserId>;
Error 自訂(v4 改用 error 參數)
z.string({ error: "Must be string" });
z.string({ error: (issue) =>
issue.input === undefined ? "Required" : "Invalid"
});
JSON Schema 轉換(v4 新增)
const jsonSchema = z.toJSONSchema(schema);
最佳實踐
- Single source of truth:schema 定義一次,type 用
z.infer 推導
- 解析 unknown JSON:用
.safeParse() 處理不信任的外部資料
- Unknown keys:預設
z.object() 會 strip — 適合清理舊格式資料
- Union 效能:大量 union 用
z.discriminatedUnion()(O(1) lookup)
- Composition:用 spread
{ ...Base.shape } 優於 .extend() chain
- Nullable fields:
.nullable() 對應 null,.optional() 對應 undefined