Zod: TypeScript-first Schema Validation

Why is schema validation needed with TypeScript?
TypeScript has become the de facto way to write JavaScript applications because it sets type guards at build time to ensure the code logic is as intended throughout the codebase. But when the application interacts with an external data source, it’s not something TypeScript can foresee and validate.
One of the most essential aspects of frontend development is collaborating with the backend developer to determine the necessary data in an optimal data structure. And there will be API changes later. How can we verify that the UI codebase and the backend are in sync? That is where Zod comes in — runtime validation.
Zod at a Glance
import * as z from "zod";
// create a schema for a post
const PostSchema = z.object({
id: z.coerce.number(), //coerce string or boolean into number
title: z.string(),
body: z.string().nullable(), // string | null
email: z.email(), //email validation
published: z.coerce.boolean.(),
tags: z.array(z.string()).default([]) //array of string and default to an empty array
});
// create a type based on the schema
type Post = z.infer<typeof PostSchema>;
const getPose = async (id: number) => {
// fetch mock data from jsonplaceholder
const response = await fetch(https://jsonplaceholder.typicode.com/posts/${id});
const post = response.json();
// the parsed result is validated and type safe
const post = PostSchema parse(post);
return post;
}
If you have a type defined already, add validation to ensure the schema is validated against the type.
const PostSchema = z.object({
id: z.coerce.number(),
title: z.string(),
body: z.string().nullable()
}) satisfies z.ZodType<Post>;
If you are excited to use Zod in your application, check out their website for additional advanced features, including error handling, custom error messages, and metadata. There is also an excellent tutorial to get you started.




