Custom Validation with Zod and "Refine"
Zod offers a lot of great ways to validate your data.
But occasionally, you might need something a little more custom.
One of Zod's powerful features is the ability to perform custom validations using the refine
method. This method allows you to add custom validation logic to a schema.
Here's how:
Custom Validation
We will start by defining a basic schema for the data you want to validate. For example, we will validate a booking form where a user has a departureDate
and a returnDate
. Here's the starter schema:
import { z } from "zod"; const bookingSchema = z.object({ departureDate: z.date(), returnDate: z.date(), })
Add Custom Validation with refine
Right now, our user can add any two dates. But we want to ensure that the returnDate
is after the departureDate
. Let's show you how you can easily add the custom validation by chaining the refine
function to your schema:
import { z } from 'zod'; const bookingSchema = z.object({ departureDate: z.date(), returnDate: z.date(), }).refine((data) => data.returnDate > data.departureDate, { message: "Return date must be after departure date", path: ["returnDate"], // Optional: Specify the path for a more precise error location }); // Now we can use our schema try { bookingSchema.parse({ departureDate: new Date('2024-03-01'), returnDate: new Date('2024-03-10'), }); console.log("Booking dates are valid!"); } catch (error) { console.error(error.errors); }
In this example, refine
takes two arguments:
- A validation function that returns
true
if the data passes the validation andfalse
otherwise. - An options object where you can specify a custom error message and the path to the data being validated.
- We also added an optional
path
to ourreturnDate
so that our errors can be more specific.
This code validates an object against your schema and the refine
function. If it fails, Zod will throw an error. You can catch this error and handle it as needed.