Add Number Validation Constraints to Zod Schemas
Learn how to enhance generated Zod schemas with number validation methods like .int(), .positive(), .min(), .max(), and .finite().
Validation
Detailed Explanation
Number Validation in Zod
The basic z.number() validator accepts any finite number. Zod provides methods to constrain numbers for specific business rules.
Common Number Validators
import { z } from "zod";
const productSchema = z.object({
// Integer only
quantity: z.number().int("Must be a whole number"),
// Positive number
price: z.number().positive("Price must be positive"),
// Range
rating: z.number().min(1, "Min rating is 1").max(5, "Max rating is 5"),
// Non-negative
stock: z.number().nonnegative("Stock cannot be negative"),
// Finite (no Infinity)
discount: z.number().finite().min(0).max(100),
// Multiple of
pageSize: z.number().int().multipleOf(10),
});
Built-in Number Validators
| Method | Validates | Example valid values |
|---|---|---|
.int() |
Integer | 1, 42, -7 |
.positive() |
> 0 | 1, 0.5, 100 |
.nonnegative() |
>= 0 | 0, 1, 100 |
.negative() |
< 0 | -1, -0.5 |
.nonpositive() |
<= 0 | 0, -1 |
.min(n) |
>= n | Depends on n |
.max(n) |
<= n | Depends on n |
.finite() |
Not Infinity | Any finite number |
.multipleOf(n) |
Divisible by n | Multiples of n |
.safe() |
Safe integer | Within Number.MAX_SAFE_INTEGER |
Chaining Validators
Validators chain naturally for precise constraints:
// Percentage: integer between 0 and 100
const percentSchema = z.number().int().min(0).max(100);
// Age: positive integer under 150
const ageSchema = z.number().int().positive().max(150);
// Price: non-negative with 2 decimal places
const priceSchema = z.number().nonnegative().multipleOf(0.01);
// Port number: integer in valid range
const portSchema = z.number().int().min(1).max(65535);
Coercion from Strings
When parsing form data or query parameters, numbers arrive as strings. Use z.coerce.number():
const querySchema = z.object({
page: z.coerce.number().int().positive().default(1),
limit: z.coerce.number().int().min(1).max(100).default(20),
});
// Parses { page: "3", limit: "50" } into { page: 3, limit: 50 }
This eliminates manual parseInt() calls and validates in one step.
Use Case
You are building an e-commerce API and need to validate that product prices are positive numbers, quantities are non-negative integers, and discount percentages fall within 0-100.