Input Validation in TypeScript APIs: Zod vs Joi vs Class-Validator
Input Validation in TypeScript APIs: Zod vs Joi vs Class-Validator Your API accepts a POST body. You trust it. A user sends { "age": "not a number" }. Your database query fails. Or worse, it succee...
Source: dev.to
Input Validation in TypeScript APIs: Zod vs Joi vs Class-Validator Your API accepts a POST body. You trust it. A user sends { "age": "not a number" }. Your database query fails. Or worse, it succeeds with bad data. Why Validate at the Boundary TypeScript types disappear at runtime. req.body is any. Your internal functions trust typed parameters, but the data crossing your API boundary is untyped. Validate once at the edge, trust everywhere inside. Zod (Recommended) Schema-first. TypeScript-native. Infers types from schemas: import { z } from "zod"; const CreateUserSchema = z.object({ name: z.string().min(1).max(100), email: z.string().email(), age: z.number().int().min(13).max(150), role: z.enum(["user", "admin"]).default("user"), }); type CreateUser = z.infer<typeof CreateUserSchema>; app.post("/users", (req, res) => { const result = CreateUserSchema.safeParse(req.body); if (\!result.success) return res.status(400).json({ errors: result.error.flatten() }); const user: CreateU