Add String Validation Constraints to Zod Schemas
Learn how to enhance generated Zod schemas with string validation methods like .email(), .url(), .min(), .max(), .regex(), and .uuid().
Validation
Detailed Explanation
String Validation in Zod
The basic z.string() validator accepts any string. Zod provides built-in methods to constrain strings further, turning your schema into a complete validation layer.
Common String Validators
import { z } from "zod";
const userSchema = z.object({
// Email validation
email: z.string().email("Invalid email address"),
// URL validation
website: z.string().url("Must be a valid URL"),
// UUID validation
id: z.string().uuid("Must be a valid UUID"),
// Length constraints
name: z.string().min(1, "Name is required").max(100, "Name too long"),
// Regex pattern
phone: z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number"),
// Starts/ends with
slug: z.string().startsWith("/", "Slug must start with /"),
// Trimmed (no leading/trailing whitespace)
username: z.string().trim().min(3).max(30),
});
Built-in String Validators
| Method | Validates | Example |
|---|---|---|
.email() |
Email format | user@example.com |
.url() |
URL format | https://example.com |
.uuid() |
UUID format | 550e8400-e29b-41d4-a716-446655440000 |
.cuid() |
CUID format | cjld2cyuq0000t3rmniod1foy |
.datetime() |
ISO datetime | 2024-03-15T10:30:00Z |
.ip() |
IP address | 192.168.1.1 |
.emoji() |
Emoji characters | Any emoji |
.min(n) |
Minimum length | At least n characters |
.max(n) |
Maximum length | At most n characters |
.length(n) |
Exact length | Exactly n characters |
.regex(re) |
Regex match | Custom pattern |
Custom Error Messages
Every validator accepts an optional error message:
z.string()
.min(8, "Password must be at least 8 characters")
.max(72, "Password must be at most 72 characters")
.regex(/[A-Z]/, "Must contain at least one uppercase letter")
.regex(/[0-9]/, "Must contain at least one number")
Transformations
Zod can transform strings during parsing:
const emailSchema = z.string()
.email()
.transform((s) => s.toLowerCase().trim());
This ensures consistent data storage regardless of how the user formats their input.
Use Case
You are building a registration form and need server-side validation that matches your client-side rules, including email format, password complexity, and username constraints.