Official NestJS documentation on pipes, covering the PipeTransform interface, built-in transformation pipes, custom validation pipes (Zod and class-validator), binding strategies, and pipe scoping.

Key takeaways

  • Pipes implement PipeTransform with a transform(value, metadata) method. They operate on arguments before the route handler is invoked, with two use cases: transformation (convert data) and validation (validate and pass-through or throw).
  • Built-in Parse* pipes include ParseIntPipe, ParseFloatPipe, ParseBoolPipe, ParseArrayPipe, ParseUUIDPipe, ParseEnumPipe, ParseDatePipe, and ParseFilePipe. DefaultValuePipe provides fallback values for optional parameters.
  • ArgumentMetadata provides type (body, query, param, custom), metatype, and data for the processed argument. The metatype is undefined if no type declaration exists or vanilla JavaScript is used — this is why DTO Classes vs Interfaces matters.
  • Schema-based validation (Zod): Pass a ZodSchema to a custom pipe’s constructor, call schema.parse() in transform(), throw BadRequestException on failure. Bind via @UsePipes(new ZodValidationPipe(schema)).
  • Decorator-based validation (class-validator): Decorate DTO properties with @IsString(), @IsInt(), etc. Use plainToInstance() from class-transformer to restore type information lost during deserialization, then validate() from class-validator. The built-in ValidationPipe does all this out of the box.
  • Pipe scoping: Pipes can be parameter-scoped (@Body(new ValidationPipe())), method-scoped (@UsePipes(...) on a route), controller-scoped, or global-scoped (app.useGlobalPipes()). Global pipes registered via APP_PIPE token support dependency injection, unlike those set via useGlobalPipes().
  • Pipes run inside the exceptions zone — when a pipe throws, it’s handled by the exceptions layer and the controller method never executes.
  • Why pipes over middleware for validation: Middleware is unaware of the execution context (handler and its parameters), making it impossible to create generic validation middleware that works across all contexts. Pipes have full access to argument metadata.

Entities and concepts

Connections to existing knowledge

The Pipes concept (from NestJS Controllers) covered the basic validation/transformation pattern. This source adds comprehensive detail on built-in pipes, custom pipe construction with both Zod and class-validator, and the full scoping model. It directly reinforces why DTO Classes vs Interfaces recommends classes — the metatype must exist at runtime. The pipe scoping model mirrors the exception filter scoping described in NestJS Exception Filters, using the same parameter/method/controller/global hierarchy and the same APP_PIPE pattern for DI-enabled global registration.