Nest.js and the Custom Validation Pipe
By: Olabisi Sulaiman
Tags: JavaScript, Nestjs, Software Development, Nodejs, Programming

Nest.js and the Custom Validation Pipe

Better validations

Photo from Morioh.

Nest.js is a progressive Node.js framework for building server-side applications. Under the hood, it uses the Express framework and can also be configured to use Fastify. It is built with and fully supports TypeScript (one of the reasons why I love this framework).

Like Angular, Nest provides us with pipes. Pipes are basically classes or functions that can take input data, transform it, and output the transformed data.

Pipes in Nest are annotated with the @injectable() decorator. Typically, in all applications, pipes can be used for the purposes of transformation and validation. In this article, I will be writing about the validation use case of a pipe.

Say we are building an application that exposes a POST endpoint to create a new item on a shopping list and you need the user to provide the following as payload to the endpoint:

Name (required)

Description (required)

Quantity (optional)

Unit price (required)

Firstly, we need to create a controller that handles the request and we need to specify that the controller should expect a body object as data from the request. The data is typed as any (for now):

Next, we need to validate the payload to ensure that it conforms with what the endpoint expects. To do this, we need to install these two packages — class-validator and class-transformer:

Now we need to create a DTO (Data Transfer Object), which is more like a model that describes how data should look. We’ll call it ItemDTO . Create a new file called item.dto.ts :

The class-validator library provides us with several decorators that can be used to describe a data type. From the snippet above:

1. name is declared as a string. The IsNotEmpty() decorator ensures that it is a required field.

2. The same goes for description .

3. unitPrice is expected to be a number and also required.

4. Notice quantity has no decorator. It is, however, declared as a number.

Now we need to change the type of the payload on our controller to be of type ItemDTO like so:

So, what we have done so far is inform our controller that the user is expected to send a payload of type itemDTO . However, what happens if the endpoint does not get any payload or the payload does not conform with the expected data types? We don’t want our application to crash, do we? We will also have to inform the user of the right data types as a guide. This is where our custom validator comes in. Nest has provided us with a built-in Validator pipe. You can read about it in the documentation.

We will need to create a new file called validation.pipe.ts . We should create a new class called CustomValidationPipe . This class should implement the PipeTransform interface, which will make us provide a transform method. The transform method takes in parameters like value (our payload) and metaData (shows more metadata about our payload). Paste the code below in the file:

1. We need to check that our payload is not empty:

Notice how HttpStatus was used. Nest has an enum of different HTTP statuses that can be leveraged upon so you don’t have to set status codes yourself. At this point, we are sure we will have a payload.

2. We need to validate the payload against the registered DTO:

Here, we make use of the plainToClass method in the class-transformer. This converts a plain (literal) object to a class (constructor) object. This is needed because we need to validate our payload as a class object. That is why we have to use the validate method from the class-validator library. It returns a Promise of Array of Errors ( Promise<ValidationError[]> ). This will ensure that our payload is validated against the provide DTO class.

3. We need to format the errors array to make it more user-friendly:

4. We need to add the Validation pipe’s class to our controller. We do that by putting it in the @UsePipes() decorator like so:

So there you have it. Pipes are a very useful concept in Nest. With the validation class that we have created, we can validate all the controllers in our application. This is very reusable and can be easily tested in a unit test. That is how useful pipes can be in an application.

Thank you for reading along. Please feel free to drop a comment below.