2025-06-13
Zod: TypeScript's Missing Runtime Validation Layer
TypeScript types vanish at runtime. Zod brings them back — and adds parse, not just check. Here's why every TypeScript API client should use it.
The TypeScript Illusion
TypeScript gives you confidence at compile time. But the moment data crosses a network boundary, that confidence evaporates. Your TypeScript types are a promise, not a guarantee.
const user = response.data as User; // 🙏 hope it matches
This as cast is a lie. If the API returns null for a required field, TypeScript won't save you.
Zod: Parse, Don't Validate
The key insight behind Zod is the distinction between validation (checking) and parsing (transforming):
const UserSchema = z.object({
id: z.number().int(),
name: z.string(),
email: z.string().email(),
});
// Throws ZodError with detailed path if invalid
const user = UserSchema.parse(response.data);
// user is now typed as { id: number; name: string; email: string }
// TypeScript KNOWS this is valid — no cast needed
After parse(), TypeScript infers the correct type. You don't need a separate type definition — z.infer<typeof UserSchema> gives it to you for free.
Generating Zod Schemas From JSON
The fastest way to start is to paste a real API response into our converter. You get a complete Zod schema with nested object schemas, array types, and z.infer type exports — ready to drop into your project.
Error Messages That Help
Zod's error messages are surgical:
ZodError: [
{ path: ["address", "zip"], message: "Expected string, received number" }
]
Compare this to "Cannot read properties of undefined" somewhere in your rendering code two call frames later.
Zod vs JSON Schema
| Zod | JSON Schema | |
|---|---|---|
| Runtime | Node/browser | Any language |
| Type inference | Automatic | Manual |
| Bundle size | ~12KB | varies |
| Ecosystem | TypeScript-only | Universal |
Use Zod inside your TypeScript application. Use JSON Schema for cross-language API contracts and OpenAPI documentation.