Introduction
TypeScript brings static typing to JavaScript, allowing developers to catch potential errors during development. However, as your codebase grows, ensuring type safety becomes increasingly challenging. Enter Zod, a TypeScript-first schema declaration and validation library that aims to make working with data structures and validation a breeze.
In this blog post, we will explore Zod in TypeScript, understand its core concepts, and walk through practical examples to demonstrate how it can be a valuable tool in your development arsenal.
Getting Started with Zod
Firstly, let’s install Zod using npm or yarn:
npm install zod
# or
yarn add zod
Requirements
- TypeScript 4.1+!
- You must enable
strict
the mode in yourtsconfig.json
. This is a best practice for all TypeScript projects.
// tsconfig.json
{
// …
"compilerOptions": {
// …
"strict": true }
}
Now, let’s dive into the basics of Zod.
Defining Schemas with Zod
Zod allows us to define data schemas, specifying the shape and types of our data. Here’s a simple example:
// Import the Zod library for data validation
import { z } from ''zod'';
// Define a schema for user objects, ensuring data integrity
const userSchema = z.object({
// Define properties with their expected types and validations:
id: z.string(), // Must be a string
username: z.string(), // Must be a string
email: z.string().email(), // Must be a string in a valid email format
age: z.number().int().positive(), // Must be a positive integer
});
// Create an example user object to validate
const user = {
id: ''123'',
username: ''john_doe'',
email: ''john.doe@example.com'',
age: 10,
};
// Validate the user object against the schema
const validatedUser = userSchema.parse(user);
// If validation succeeds, validatedUser will contain the parsed user object.
// If validation fails, an error will be thrown.
console.log(validatedUser); // Output the validated user object or any errors
In this example, we define a schema for a user object, specifying that id
and username
should be strings, email
should be a valid email address, and age
should be a positive integer. The parse
method validates the user object against the schema.
Custom Validation and Transformation
Zod allows us to add custom validation and transformation functions. Let’s enhance our user schema with a custom validation for the username and a transformation for the age:
// Define a schema for product objects, ensuring data integrity
const productSchema = z.object({
// Define properties with their expected types and validations:
id: z.string(), // Must be a string
name: z.string(), // Must be a string
price: z.number().int().positive(), // Must be a positive integer
});
// Custom validation function for name
const isValidProductname = (name: string) => /^[a-zA-Z0-9_]+$/.test(name);
// Custom transformation function for price
const doublePrice = (price: number) => price * 2;
// Extend the product schema with custom validation and transformation
const extendedProductSchema = productSchema.extend({
name: z.string().refine(isValidProductname, {
message: ''Invalid Product format'',
}),
price: z.number().transform(doublePrice),
});
// Example user with a custom name and price transformation
const productWithCustomData = {
id : "123",
name: ''chair'',
price: 15,
};
// Validate and transform the product data against the extended schema
const validatedProductWithCustomData = extendedProductSchema.parse(productWithCustomData);
console.log(validatedProductWithCustomData);
// { id: ''123'', name: ''chair'', price: 30 }
Here, we use the refine
method for custom validation of the name
field and the transform
method to double the value of the price
field.
Array Validation
Let’s consider a scenario where we have an array of user objects, and we want to ensure that each user in the array conforms to a specific schema:
// Define a schema for individual user objects
const userSchema = z.object({
id: z.string(),
username: z.string(),
email: z.string().email(),
age: z.number().int().positive(),
});
// Define a schema for arrays of user objects
const arrayOfUsersSchema = z.array(userSchema);
// Example array of users to validate
const users = [
{
id: ''123'',
username: ''john_doe'',
email: ''john.doe@example.com'',
age: 25,
},
{
id: ''456'',
username: ''the_rock'',
email: ''the.rock@example.com'',
age: 25,
},
];
Here, arrayOfUsersSchema
is a schema that expects an array of objects, where each object adheres to the userSchema
. The parse
method ensures that each element in the array satisfies the specified schema.
Advanced Schema Composition (or, and)
Zod supports advanced schema composition with union and intersection types. Let’s create schemas for both individuals and organizations:
const individualSchema = z.object({
firstName: z.string(),
lastName: z.string(),
});
const organizationSchema = z.object({
organizationName: z.string(),
registrationNumber: z.string(),
});
// Union type: person or organization
const entitySchema = individualSchema.or(organizationSchema);
// Example individual data
const individualData = {
firstName: ''John'',
lastName: ''Doe'',
};
const validatedIndividual = entitySchema.parse(individualData);
console.log(validatedIndividual);
// InterSection type: person and organization
const individualAndOrganizationSchema = individualSchema.and(organizationSchema);
const individualDataIntersection = {
firstName: ''John'',
lastName: ''Doe'',
organizationName : ''08744'',
registrationNumber : ''94774'',
};
const validatedIndividualInterSection = individualAndOrganizationSchema.parse(individualDataIntersection);
console.log(validatedIndividualInterSection);
In this example, we define separate schemas for individuals and organizations, then create a union type (or
) and an intersection type (and
) to compose more complex schemas.
Conclusion
Zod is a powerful tool for defining, validating, and transforming data structures in TypeScript. With its concise syntax and extensive features, it can enhance the robustness and maintainability of your codebase. As you explore Zod further, you’ll find it to be a valuable asset in handling data with confidence.
Remember to check the official documentation for more advanced features and options provided by Zod. Happy coding!