Introduction to Zod
Learning objectives
- You know of the Zod validation library and know how to use Zod to validate data.
- You know of some of the validation primitives that Zod offers.
- You know what coercion is and what it is used for.
Zod is a validation library that is based on the notion of pre-defining the expected data format, i.e. "the schema". After a schema has been defined, it can be used to validate provided input.
Running zod and validating an email
As a starting point, try out the following program. The program imports Zod, creates a validation rule for an email, and then validates two strings. The first string is not an email, while the second string is an email.
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
const validator = z.string().email();
let result = validator.safeParse("This is not an email");
console.log(result);
result = validator.safeParse("this-is-an@email.com");
console.log(result);
Below, the program has been saved to a file called zod-test.js
, which is then run using deno run zod-test.js
.
deno run zod-test.js
{ success: false, error: [Getter] }
{ success: true, data: "this-is-an@email.com" }
As we see from the above output, the first validation fails, while the second validation succeeds. The success (or failure) of the validation is stored in the success
attribute of the validation result. In addition, in the case the validation succeeds, the validated data is stored in the data
attribute of the validation result.
Validation primitives
Zod comes with a variety of validation primitives that can be used to validate data, ranging from strings to numbers and booleans. For some of these, like strings, there are additional specific rules, such as the email validation shown above.
As an example, the following program shows simply how to validate whether an input is a string.
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
const validator = z.string();
let result = validator.safeParse("a string");
console.log(result);
result = validator.safeParse(123);
console.log(result);
The primitives are highlighted in the documentation of Zod at https://zod.dev/?id=primitives.
Validating an object
In the case of web applications and forms, the data that is submitted is parsed as an object, where the object contains the values for the form fields. Let's modify the previous example so that we validate an object instead of a string.
In the following, we create a validator that validates an object. The object must contain an attribute email
that needs to be an email address.
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
const validator = z.object({
email: z.string().email(),
});
let result = validator.safeParse("this-is-an@email.com");
console.log(result);
result = validator.safeParse({ email: "this-is-an@email.com" });
console.log(result);
deno run zod-test.js
{ success: false, error: [Getter] }
{ success: true, data: { email: "this-is-an@email.com" } }
Coercion
Coercion refers to the process of converting data from one type to another. In the case of validation, coercion is used to convert data from one type to another before the validation is performed. As an example, if we would be validating a year of birth, we might want to convert the year of birth to a number before validation.
Coercion is especially relevant when working with forms, as all form data is submitted as strings.
Zod supports coercion out of the box with coerce
, which is an attribute of z
, which is followed by the primitive type into which the data should be coerced into. As an example, the following code coerces the year of birth to a number.
const validator = z.object({
email: z.string().email(),
yearOfBirth: z.coerce.number().min(1900).max(2030),});
Retaining only relevant data
Zod comes with a feature where the validation retains only the relevant data. This is illustrated in the following example, where the object that we want to validate has an attribute garbage
in addition to the attribute email
. When we run the validation, the object in the data
attribute of the validation result contains only the email
.
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
const validator = z.object({
email: z.string().email(),
});
let result = validator.safeParse({
garbage: "not needed",
email: "another@email.com",
});
console.log(result);
deno run zod-test.js
{ success: true, data: { email: "another@email.com" } }