</>
⌕
Senior #validation#zod#runtime#type-safety

Type TypeScript và runtime validation: vì sao cần zod?

⚡ Trả lời nhanh

Type bị xóa khi compile nên không bảo vệ dữ liệu vào lúc chạy (API response, JSON.parse, form, env). Thư viện schema như zod định nghĩa schema một lần, vừa validate runtime vừa suy ra type bằng `z.infer`, giúp biên giới hệ thống (trust boundary) an toàn thật sự thay vì chỉ ép kiểu bằng `as`.

Vấn đề

const user = JSON.parse(body) as User;   // compile OK, nhưng không hề kiểm tra
user.email.toLowerCase();                // có thể nổ runtime nếu thiếu email

as User chỉ nói dối compiler. JSON.parse và response.json() trả any/unknown; nguồn bên ngoài luôn phải được xem là không tin cậy.

Giải pháp: schema là nguồn sự thật duy nhất

import { z } from "zod";

const User = z.object({
  id: z.number().int(),
  email: z.string().min(3),
  age: z.number().optional(),
});
type User = z.infer<typeof User>;        // type suy ra từ schema

const result = User.safeParse(JSON.parse(body));
if (!result.success) return res.status(400).json(result.error.issues);
const user = result.data;                // đã được narrow thành User
  • Validate ở biên: request body, query, env vars, response từ service ngoài, localStorage.
  • Bên trong (sau khi đã validate) tin vào type, không cần kiểm tra lặp.
  • Schema hỗ trợ transform và coerce (chuỗi sang number/Date), union, refinement; dùng được cho form (react-hook-form) và tRPC.
  • Lựa chọn khác: Valibot (nhẹ, tree-shakeable), ArkType, io-ts, Typia (sinh code lúc build).
🃏 Ôn bằng flashcard