What is Zod JavaScript?
Zod is a library designed for JavaScript and TypeScript that assists developers in establishing the schema for their data. In this context, a schema serves as a framework that outlines the structure and limitations of the data. Zod enables developers to articulate these schemas in a succinct manner and subsequently employ them for data validation during runtime.
In straightforward terms, Zod serves as a library for schema declaration and validation specifically designed for JavaScript. Utilizing Zod, developers are able to create schemas for various types of data, encompassing primitive data types, objects, arrays, and additional structures.
Why do we need Zod in JavaScript?
In JavaScript, Zod offers runtime schema validation capabilities. Through the use of schema validation, developers can ensure that data adheres to a predetermined standard set by them.
Acquiring user data through forms and transmitting information to APIs is advantageous in various contexts. Generally, JavaScript offers schema validation exclusively during the compile time; in contrast, Zod facilitates validation during runtime.
Runtime Validation
In JavaScript, Zod goes beyond mere type definitions; it provides runtime data validation. This capability is crucial when working with external inputs such as user submissions, responses from APIs, or entries in a database, where the reliability of the incoming data cannot be completely guaranteed.
Developer Experience
It is highly regarded for its syntax that is conducive to developers. This allows us to construct schemas that appear intuitive and organic, resulting in code that is cleaner and easier to maintain.
Installation of Zod in JavaScript
To incorporate Zod into your project, you have the option to install it using either npm or yarn:
npm install zod
If you are using yarn, use the following command:
yarn add zod
After the installation is complete, you are able to import Zod and begin creating your schemas.
import { z } from 'zod';
const userSchema = z.object({
username: z.string(),
age: z.number(),
email: z.string().email(),
});
In the preceding example, we established a basic schema for a user object that outlines the requirement for a username, age, and email. The username and email are expected to be strings, while the age is designated as a number, with the email following a standard email format.
Features of Zod in JavaScript
Zod includes a variety of features that enhance its functionality. Below are some of the key features:
Static Typing
In JavaScript, Zod is developed upon TypeScript, allowing us to leverage the static type system of TypeScript which offers a compile-time assurance that our code is processing data appropriately. By employing static typing, we can prevent numerous issues and significantly reduce development time by identifying errors early in the coding process.
Schema Validation
Utilizing Zod in JavaScript allows for the straightforward creation of intricate data schemas encompassing a diverse array of schema types, including strings, numbers, Booleans, arrays, objects, and beyond. Additionally, it enables the establishment of custom schemas and validators tailored to meet our unique requirements.
Custom Error Messages
In JavaScript, Zod offers an interface for personalizing error messages. This feature enables you to deliver clearer and more detailed error messages, assisting end-users in comprehending the issues that arose during the validation process.
Nesting
In JavaScript, Zod provides the capability to nest schemas, facilitating the creation of intricate validation rules. This functionality is particularly advantageous when dealing with nested objects and arrays.
Async Validation
It additionally offers an API designed for executing asynchronous validation. This feature enables you to verify data that necessitates asynchronous processes, including network calls. There is no requirement to pause for the data to return before proceeding with the validation.
Lightweight
In JavaScript, Zod is a minimalistic library characterized by its compact API surface. This design choice facilitates a straightforward learning curve and usage experience.
How to avoid errors?
In JavaScript, to prevent issues when parsing does not succeed, we should employ the safeParse function. This function will return a status code of 400 along with an object that has the success property assigned to true if the string is parsed correctly. Conversely, if the parsing fails, the success property will be set to false. In this scenario, the function will also provide an error property that includes the error object.
Example
For illustration purposes, we will utilize the safeParse function. Let's execute the code to observe the resulting output:
import { z } from "zod"
const userInput = z.string().min(5).max(10);
const result = userInput.safeParse("Hello Zod and Typescript");
if (result.success) {
console.log('Valid Data', result.data);
} else {
console.error('Invalid Data', result.error.message);
}
This code will display "Valid Data" alongside the data if the string has been successfully parsed. If the parsing fails, it will instead output "Invalid Data" along with the corresponding error message.
Why do we use the Zod in JavaScript?
There are several justifications for utilizing Zod in JavaScript. Below are some of the key reasons:
Type Safety
In JavaScript, Zod seamlessly integrates with the language, enabling us to establish schemas that possess strong typing. This functionality guarantees that your data conforms to the anticipated structure, thereby minimizing the likelihood of encountering runtime errors.
Ease of use
In JavaScript, Zod offers an intuitive application programming interface (API) that simplifies the process of defining and validating schemas. Its straightforward syntax is both easy to comprehend and to author, making it approachable for developers who are either new to JavaScript or unfamiliar with schema validation.
Comprehensive validation
In JavaScript, Zod provides extensive support for various data types and validation criteria right from the start, encompassing basic primitives such as strings and numbers, as well as intricate nested structures including objects and arrays.
Extensibility
This functionality permits the development of personalized validation logic, allowing you to customize the validation procedure to meet your particular requirements.
Security
In JavaScript, Zod aids in the prevention of harmful payloads from being processed by validating incoming data. This is essential for safeguarding your application against prevalent security risks, including SQL injection and various other types of data-driven attacks.
Integration
Zod offers straightforward integration with a variety of frameworks and libraries, such as React, Express, and others, making it a flexible option suitable for a range of project types.
Using Zod in both Backend and Frontend
In a standard full-stack application, it is common to require validation of identical data on both the client side and the server side. To prevent redundancy and maintain uniformity, it is advisable to establish your Zod schemas within a shared package that is accessible in both environments. By adopting this methodology, we not only minimize code duplication but also guarantee that both the client and server are aligned on the data structure.
Creating a Shared Zod Schema Package
In this section, we will explore the process of developing a shared Zod schema package that can be published on npm, enabling its utilization in both your frontend and backend applications.
Setup the Project
To begin, you should establish a new directory designated for your shared package and initialize it using npm:
mkdir my-shared-schemas
cd my-shared-schemas
npm init -y
Install Zod
Now, install Zod as a dependency:
npm install zod
Define your schema
Establish a directory specifically for schemas and outline your Zod schemas within a designated file, such as userSchema.ts:
// src/schemas/userSchema.ts
import { z } from 'zod';
export const userSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
Build and Publish the package
Modify your package.json to incorporate the essential build scripts and get the package ready for distribution. You may utilize a tool such as tsc to compile your TypeScript code:
{
"name": "my-shared-schemas",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"typescript": "^4.0.0"
},
"dependencies": {
"zod": "^3.0.0"
}
}
Add a tsconfig.json file to configure TypeScript:
{
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs",
"target": "es6",
"declaration": true,
"strict": true,
"esModuleInterop": true
},
"include": ["src"]
}
Now, build and publish the package:
npm run build
npm publish
Using the shared schema package
Having published your shared schema package to npm, you can now proceed to install and utilize it in both your frontend and backend applications.
In the Frontend:
Install the shared schema package:
npm install my-shared-schemas
Utilize the schemas to ensure that data is validated prior to transmitting it to the backend:
import { userSchema } from 'my-shared-schemas';
const userData = {
name: "Rohit Kumar",
age: 20,
email: "rohit@example.com",
};
try {
userSchema.parse(userData);
// Send valid data to backend
} catch (e) {
console.error(e.errors);
// Handle validation errors
}
In the Backend:
Install the shared schema package:
npm install my-shared-schemas
Utilize the schemas to verify the data received from the frontend:
import express from 'express';
import { userSchema } from 'my-shared-schemas';
const app = express();
app.use(express.json());
app.post('/users', (req, res) => {
try {
userSchema.parse(req.body);
// Handle valid data
res.status(200).send("User data is valid");
} catch (e) {
res.status(400).send(e.errors);
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
By establishing and distributing your Zod schemas throughout both the frontend and backend, it is essential to guarantee that data undergoes uniform validation at each stage. This practice not only elevates the quality of your code but also fortifies security by obstructing the processing of invalid or potentially harmful data by your server.