R

Request Validation

Validate and parse request data with type-safe schemas using Zod.

Code

typescript
1import { z } from "zod";
2
3// Define schemas with Zod
4const UserSchema = z.object({
5 name: z.string().min(2).max(50),
6 email: z.string().email(),
7 age: z.number().int().min(0).max(150).optional(),
8 role: z.enum(["user", "admin", "moderator"]).default("user"),
9});
10
11const CreatePostSchema = z.object({
12 title: z.string().min(1).max(200),
13 content: z.string().min(10),
14 tags: z.array(z.string()).max(5).optional(),
15 published: z.boolean().default(false),
16});
17
18// Infer TypeScript types from schemas
19type User = z.infer<typeof UserSchema>;
20type CreatePost = z.infer<typeof CreatePostSchema>;
21
22// Validation function with error handling
23function validate<T>(
24 schema: z.ZodSchema<T>,
25 data: unknown
26): { success: true; data: T } | { success: false; errors: string[] } {
27 const result = schema.safeParse(data);
28
29 if (result.success) {
30 return { success: true, data: result.data };
31 }
32
33 const errors = result.error.errors.map(
34 (err) => `${err.path.join(".")}: ${err.message}`
35 );
36
37 return { success: false, errors };
38}
39
40// Example validation
41const validUser = {
42 name: "Alice",
43 email: "alice@example.com",
44 age: 25,
45};
46
47const invalidUser = {
48 name: "A",
49 email: "not-an-email",
50 age: -5,
51};
52
53console.log("Valid user:", validate(UserSchema, validUser));
54// { success: true, data: { name: "Alice", email: "...", age: 25, role: "user" } }
55
56console.log("Invalid user:", validate(UserSchema, invalidUser));
57// { success: false, errors: [...] }
58
59// Custom validators
60const PasswordSchema = z.string()
61 .min(8, "Password must be at least 8 characters")
62 .regex(/[A-Z]/, "Password must contain an uppercase letter")
63 .regex(/[a-z]/, "Password must contain a lowercase letter")
64 .regex(/[0-9]/, "Password must contain a number");
65
66const RegisterSchema = z.object({
67 username: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/),
68 email: z.string().email(),
69 password: PasswordSchema,
70 confirmPassword: z.string(),
71}).refine((data) => data.password === data.confirmPassword, {
72 message: "Passwords don't match",
73 path: ["confirmPassword"],
74});
75
76// Test password validation
77const registration = {
78 username: "alice123",
79 email: "alice@example.com",
80 password: "SecurePass1",
81 confirmPassword: "SecurePass1",
82};
83
84console.log("Registration:", validate(RegisterSchema, registration));

Run this example locally

$ npx ts-node backend/validation.ts