It is best practice to validate the correctness of any data sent into a web application. To automatically validate incoming requests, Nest provides several pipes available right out-of-the-box:
ValidationPipe makes use of the powerful class-validator package and its declarative validation decorators. The
ValidationPipe provides a convenient approach to enforce validation rules for all incoming client payloads, where the specific rules are declared with simple annotations in local class/DTO declarations in each module.
In the Pipes chapter, we went through the process of building simple pipes and binding them to controllers, methods or to the global app to demonstrate how the process works. Be sure to review that chapter to best understand the topics of this chapter. Here, we'll focus on various real world use cases of the
ValidationPipe, and show how to use some of its advanced customization features.
Using the built-in ValidationPipe
info Hint The
ValidationPipeis exported from the
Because this pipe uses the
class-transformer libraries, there are many options available. You configure these settings via a configuration object passed to the pipe. Following are the built-in options:
In addition to these, all
class-validator options (inherited from the
ValidatorOptions interface) are available:
|If set to true, validator will skip validation of all properties that are missing in the validating object.|
|If set to true, validator will strip validated (returned) object of any properties that do not use any validation decorators.|
|If set to true, instead of stripping non-whitelisted properties validator will throw an exception.|
|If set to true, attempts to validate unknown objects fail immediately.|
|If set to true, validation errors will not be returned to the client.|
|This setting allows you to specify which exception type will be used in case of an error. By default it throws |
|Takes an array of the validation errors and returns an exception object to be thrown.|
|Groups to be used during validation of the object.|
|If set to true, the validation will not use default messages. Error message always will be |
|Indicates if target should be exposed in |
|Indicates if validated value should be exposed in |
info Notice Find more information about the
class-validatorpackage in its repository.
We'll start by binding
ValidationPipe at the application level, thus ensuring all endpoints are protected from receiving incorrect data.
To test our pipe, let's create a basic endpoint.
info Hint Since TypeScript does not store metadata about generics or interfaces, when you use them in your DTOs,
ValidationPipemay not be able to properly validate incoming data. For this reason, consider using concrete classes in your DTOs.
Now we can add a few validation rules in our
CreateUserDto. We do this using decorators provided by the
class-validator package, described in detail here. In this fashion, any route that uses the
CreateUserDto will automatically enforce these validation rules.
With these rules in place, if a request hits our endpoint with an invalid
400 Bad Request code, along with the following response body:
In addition to validating request bodies, the
ValidationPipe can be used with other request object properties as well. Imagine that we would like to accept
:id in the endpoint path. To ensure that only numbers are accepted for this request parameter, we can use the following construct:
FindOneParams, like a DTO, is simply a class that defines validation rules using
class-validator. It would look like this:
Disable detailed errors
Error messages can be helpful to explain what was incorrect in a request. However, some production environments prefer to disable detailed errors. Do this by passing an options object to the
As a result, detailed error messages won't be displayed in the response body.
ValidationPipe can also filter out properties that should not be received by the method handler. In this case, we can whitelist the acceptable properties, and any property not included in the whitelist is automatically stripped from the resulting object. For example, if our handler expects
password properties, but a request also includes an
age property, this property can be automatically removed from the resulting DTO. To enable such behavior, set
When set to true, this will automatically remove non-whitelisted properties (those without any decorator in the validation class).
Alternatively, you can stop the request from processing when non-whitelisted properties are present, and return an error response to the user. To enable this, set the
forbidNonWhitelisted option property to
true, in combination with setting
Transform payload objects
ValidationPipe can automatically transform payloads to be objects typed according to their DTO classes. To enable auto-transformation, set
true. This can be done at a method level:
To enable this behavior globally, set the option on a global pipe:
With the auto-transformation option enabled, the
ValidationPipe will also perform conversion of primitive types. In the following example, the
findOne() method takes one argument which represents an extracted
id path parameter:
By default, every path parameter and query parameter comes over the network as a
string. In the above example, we specified the
id type as a
number (in the method signature). Therefore, the
ValidationPipe will try to automatically convert a string identifier to a number.
In the above section, we showed how the
ValidationPipe can implicitly transform query and path parameters based on the expected type. However, this feature requires having auto-transformation enabled.
Alternatively (with auto-transformation disabled), you can explicitly cast values using the
ParseBoolPipe (note that
ParseStringPipe is not needed because, as mentioned earlier, every path parameter and query parameter comes over the network as a
string by default).
info Hint The
ParseBoolPipeare exported from the
Parsing and validating arrays
TypeScript does not store metadata about generics or interfaces, so when you use them in your DTOs,
ValidationPipe may not be able to properly validate incoming data. For instance, in the following code,
createUserDtos won't be correctly validated:
To validate the array, create a dedicated class which contains a property that wraps the array, or use the
In addition, the
ParseArrayPipe may come in handy when parsing query parameters. Let's consider a
findByIds() method that returns users based on identifiers passed as query parameters.
This construction validates the incoming query parameters from an HTTP
GET request like the following:
WebSockets and Microservices
While this chapter shows examples using HTTP style applications (e.g., Express or Fastify), the
ValidationPipe works the same for WebSockets and microservices, regardless of the transport method that is used.
Read more about custom validators, error messages, and available decorators as provided by the
class-validator package here.