Pipes help process and validate data before it reaches your code. Binding pipes lets you control where and how this happens.
Pipe binding (parameter, method, controller, global) in NestJS
1. Parameter binding: @Get(':id') method(@Param('id', Pipe) id: string) {} 2. Method binding: @UsePipes(Pipe) method() {} 3. Controller binding: @UsePipes(Pipe) @Controller() class MyController {} 4. Global binding: app.useGlobalPipes(new Pipe());
Use @UsePipes() decorator for method and controller binding.
Parameter binding applies pipe only to that parameter.
ParseIntPipe.@Get(':id') getById(@Param('id', ParseIntPipe) id: number) { return id; }
create method.@UsePipes(ValidationPipe)
@Post()
create(@Body() data: CreateDto) {
return data;
}UserController will validate input data.@UsePipes(ValidationPipe) @Controller('users') class UserController { @Post() create(@Body() data: CreateUserDto) { return data; } }
async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); await app.listen(3000); }
This example shows pipe binding at all levels: parameter (ParseIntPipe), controller (ValidationPipe), and global (ValidationPipe in main).
import { Controller, Get, Param, UsePipes, ValidationPipe, ParseIntPipe } from '@nestjs/common'; @Controller('items') @UsePipes(new ValidationPipe()) export class ItemsController { @Get(':id') getItem(@Param('id', ParseIntPipe) id: number) { return { itemId: id }; } } // main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); await app.listen(3000); } bootstrap();
Pipes run in this order: global, controller, method, then parameter.
Parameter pipes override method or controller pipes for that parameter.
Use pipes to keep your code clean by handling validation and transformation outside your main logic.
Pipes process data before your code uses it.
You can bind pipes to parameters, methods, controllers, or globally.
Binding location controls how widely the pipe applies.
Practice
Solution
Step 1: Understand parameter-level pipe binding
Binding a pipe to a parameter means the pipe runs only on that parameter to transform or validate it before the method uses it.Step 2: Differentiate from other bindings
Middleware and global pipes affect broader scopes, not just a single parameter. Routing is unrelated to pipes.Final Answer:
To transform or validate the specific parameter before the method uses it -> Option DQuick Check:
Parameter pipe = transform/validate parameter [OK]
- Confusing parameter pipes with global pipes
- Thinking pipes define routes
- Mixing middleware with pipes
Solution
Step 1: Identify global pipe binding syntax
Global pipes are bound using the app instance with app.useGlobalPipes(pipeInstance).Step 2: Differentiate from controller and method bindings
@UsePipes decorator applies pipes at controller or method level, not globally.Final Answer:
app.useGlobalPipes(new ValidationPipe()); -> Option BQuick Check:
Global pipe = app.useGlobalPipes() [OK]
- Using @UsePipes for global binding
- Binding pipes inside method parameters for global effect
- Confusing middleware with pipes
age='25' (string)?
import { Controller, Get, Query, ParseIntPipe } from '@nestjs/common';
@Controller('users')
export class UserController {
@Get()
getUser(@Query('age', ParseIntPipe) age: number) {
return { age, type: typeof age };
}
}Solution
Step 1: Understand ParseIntPipe effect on query parameter
ParseIntPipe converts the string '25' to the number 25 before passing it to the method.Step 2: Check returned object values
The method returns an object with age as number 25 and type as 'number'.Final Answer:
{"age": 25, "type": "number"} -> Option CQuick Check:
ParseIntPipe converts string to number [OK]
- Assuming age remains string
- Expecting runtime error on conversion
- Confusing type of returned value
import { Controller, Get, UsePipes, ValidationPipe, Query } from '@nestjs/common';
@Controller('products')
export class ProductController {
@Get()
@UsePipes(ValidationPipe)
findProduct(@Query('id') id: string) {
return id;
}
}Solution
Step 1: Check @UsePipes decorator usage
@UsePipes expects an instance of a pipe, so ValidationPipe must be called with 'new'.Step 2: Validate other parts
@UsePipes can be used on methods, Query decorator is valid, Controller decorator is correct.Final Answer:
ValidationPipe should be instantiated with 'new' keyword in @UsePipes -> Option AQuick Check:
@UsePipes needs pipe instances [OK]
- Passing pipe class instead of instance
- Thinking @UsePipes only works on controllers
- Missing pipe on parameter is not an error
Solution
Step 1: Understand scope of pipes for separation of concerns
Trimming strings is specific to this controller's inputs, so controller-level binding keeps it scoped and clean.Step 2: Apply number validation globally
Number validation is common across the app, so global binding ensures consistent validation everywhere.Final Answer:
Bind the trim pipe at controller level and the number validation pipe globally -> Option AQuick Check:
Controller pipe for specific, global pipe for common validation [OK]
- Binding all pipes globally causing unnecessary processing
- Binding all pipes only on parameters causing repetition
- Mixing global and method-level without clear reason
Ready to prove it?
Pass the test and this pattern moves unknown
