DEV Community

Robert
Robert

Posted on • Edited on

Zod simple tutorial

Node-Typescript-Zod

In the following example will be creating a simple REST API, and validating it with zod.

You can contact me by telegram if you need to hire a Full Stack developer..

You can also contact me by discord Appu#9136.

creating our project

  • open your terminal and type the following
  • mkdir node-typescript-zod-tut
  • cd node-typescript-zod-tut
  • npm init --y
  • code .

Packages

  • express
  • zod
  • typescript
  • ts-node-dev
  • @types/express

Production packages

npm i express zod
Enter fullscreen mode Exit fullscreen mode

Development packages

npm i typescript ts-node-dev @types/express -D
Enter fullscreen mode Exit fullscreen mode

project file structure:

node-typescript-zod-tutorial/
├── node_modules/
├── src/
│ ├── routes/
│ ├── schema/
│ └── index.ts
├── tsconfig.json
└── package.json

Project setup

1- Add this line in your package.json, with ts-node-dev we can run .ts files, --respawn to re-run automatically after a change in our file.

 "scripts": {
    "dev": "ts-node-dev --respawn src/index.ts"
  },
Enter fullscreen mode Exit fullscreen mode

2- Type the following line in your console,npx tsc --init it will create a tsconfig.json, now in our tsconfig.json file let's use "ctrl+f" to find rootDir and outDir, uncomment rootDir and type this "rootDir": "./src", uncomment outDir and type this "outDir": "./dist", .

Let's code

1-creating our index.ts
index.ts

import express from 'express'


//initialiaztion
const app = express()


//server
app.listen(3000, () => {
  console.log('listening on port 3000')
})
Enter fullscreen mode Exit fullscreen mode

Now let's run npm run dev and we should get this:

listening on port 3000
Enter fullscreen mode Exit fullscreen mode

2- Let's go to our routes folder and create this file contacts.route.ts

contacts.route.ts

import { Router, Require, Response } from "express";

const route = Router()

route.post('/contacts', (req: Require, res: Response) => {
  console.log(req.body)
  res.json({message: 'contact created'})
})

export default route
Enter fullscreen mode Exit fullscreen mode

Let's go back to index.ts and import our route.

index.ts

import express from 'express'
import contactsRoutes from './routes/contacts.routes'

//initialiaztion
const app = express()

//middlewares
app.use(express.json())

//routes
app.use(contactsRoutes)

//server
app.listen(3000, () => {
  console.log('listening on port 3000')
})
Enter fullscreen mode Exit fullscreen mode

let's try our API, I am gonna use the REST client VScode extension, but feel free to use postman, insomnia, or whatever you want.

We want to pass some fields, let's use contact first name, last name, email and a phone number.

route-test

3- Let's create our zod schema, go to our schema folder and create contacts.schema.ts file.

In this code we are creating our ContactSchema where firstName field should be a string with .string() and cannot be empty using .nonempty().

contacts.schema.ts

import { z } from "zod";

export const ContactSchema = z.object({
  firstName: z
  .string()
  .nonempty(),
})
Enter fullscreen mode Exit fullscreen mode

Let's go back to contacts.route.ts and import our schema.

import { Router, Request, Response } from "express";
import { ContactSchema } from "../schema/contacts.schema";

const route = Router()

route.post('/contacts',(req: Request, res: Response) => {
  console.log(req.body)
  try {
    const result = ContactSchema.parse(req.body);
    console.log(result)
    res.json({messasge: 'contact created'})
  } catch (error) {
    return res.status(500).json({ message: error });
  }
})

export default route
Enter fullscreen mode Exit fullscreen mode

Let's try out our post route again and see what happens.

Image description

Now we are getting some errors, "expected": "string", because "message": "Expected string, received number".

Let's fix a little bit our code to display our error message in a better way, first let's import ZodError from zod, and change the catch block to display only the error messages from zod and if the error is not coming from zod display the server error

import { Router, Request, Response } from "express";
import { ContactSchema } from "../schema/contacts.schema";
import { ZodError }from "zod";

const route = Router()

route.post("/contacts", (req: Request, res: Response) => {
  console.log(req.body);
  try {
    const result = ContactSchema.parse(req.body);
    console.log(result);
    res.json({ messasge: "contact created" });
  } catch (error) {
    if (error instanceof ZodError) {
      return res
        .status(400)
        .json(error.issues.map((issue) => ({ message: issue.message })));
    }
    return res.status(500).json({ message: error });
  }
});

export default route
Enter fullscreen mode Exit fullscreen mode

Now we're getting this message .

apitest4

Now let's the with firstName field empty.

apitest

We can also change the error message, let's go back to contacts.schema.ts, and add this to .nonempty()

import { z } from "zod";

export const ContactSchema = z.object({
  firstName: z
  .string()
  .nonempty('first name is required'),
})
Enter fullscreen mode Exit fullscreen mode

Now we're getting this.

apitest5

Let's add the rest of the fields.

import { z } from "zod";

export const ContactSchema = z.object({
  firstName: z
  .string()
  .nonempty('Name is Required'),
  lastName: z
  .string()
  .nonempty('Last Name is Required'),
  email: z
  .string()
  .email({message: 'Email is not valid'})
  .nonempty('Email is Required'),
  phone: z
  .string()
  .nonempty('Phone is Required'),
})
Enter fullscreen mode Exit fullscreen mode

Let's do a couple of tests.

Image description

Image description

That would be a basic idea of validation with Zod.

You can contact me by telegram if you need to hire a Full Stack developer..

You can also contact me by discord..

I hope you find this helpful. please let me know what you think, thank you.

Top comments (0)