NestJS Decorators

Decorators are special labels you attach to classes, methods, properties, or parameters. They tell NestJS what role each piece of code plays — without cluttering the code with configuration logic. You have already seen decorators like @Controller(), @Get(), and @Injectable(). This topic explains how decorators work and covers the full set NestJS provides.

What Is a Decorator?

A decorator is a function that runs at the time your class or method is defined — not when it is called. It reads metadata and modifies behavior. The @ symbol before a name signals that it is a decorator.

Think of a decorator like a sticker on a package. The package (your class) has content inside. The sticker (decorator) on the outside tells the postal service (NestJS) exactly how to handle it — fragile, express delivery, temperature sensitive. The postal service reads the sticker and acts accordingly. Your package does not change — only how it gets treated changes.

Class Decorators

Class decorators attach to the top of a class and describe what that class is:

Decorator         | What It Marks
------------------|-------------------------------------------
@Module()         | A NestJS module
@Controller()     | An HTTP controller
@Injectable()     | A provider (service, guard, pipe, etc.)
@Global()         | A module available application-wide
@Catch()          | An exception filter
@Controller('products')       // Class decorator
export class ProductsController { ... }

@Injectable()                 // Class decorator
export class ProductsService { ... }

Method Decorators

Method decorators sit on individual methods inside a controller and define how HTTP requests reach them:

Decorator       | HTTP Method Mapped
----------------|-------------------
@Get()          | GET request
@Post()         | POST request
@Put()          | PUT request
@Patch()        | PATCH request
@Delete()       | DELETE request
@Head()         | HEAD request
@Options()      | OPTIONS request
@All()          | Any HTTP method

Additional method decorators control response behavior:

@HttpCode(204)          // Sets the response status code
@Header('key', 'val')   // Adds a response header
@Redirect('/home', 301) // Redirects to another URL
@Render('index')        // Renders a template view

Parameter Decorators

Parameter decorators extract specific data from the incoming HTTP request and pass it directly into your method:

Decorator               | Extracts
------------------------|-----------------------------------------
@Param('id')            | URL param: /users/:id
@Query('filter')        | Query string: ?filter=active
@Body()                 | Entire request body (JSON)
@Body('email')          | One field from the request body
@Headers()              | All request headers
@Headers('auth')        | One specific header
@Req()                  | Full Express request object
@Res()                  | Full Express response object
@Ip()                   | Client's IP address
@HostParam()            | Sub-domain hostname parameter
@Session()              | Session object
@Get(':id')
findOne(
  @Param('id') id: string,          // Extracts :id from URL
  @Query('format') format: string,  // Extracts ?format=json
) {
  return this.usersService.findOne(+id);
}

How Decorators Are Applied — A Visual

@Controller('users')          ← Class decorator (sets base path)
export class UsersController {

  @Get()                      ← Method decorator (GET /users)
  findAll() { ... }

  @Get(':id')                 ← Method decorator (GET /users/:id)
  findOne(
    @Param('id') id: string   ← Parameter decorator (extracts :id)
  ) { ... }

  @Post()                     ← Method decorator (POST /users)
  create(
    @Body() dto: CreateUserDto  ← Parameter decorator (request body)
  ) { ... }

}

Property Decorators

Property decorators sit on class properties. NestJS uses them in entity definitions (when working with TypeORM) and in validation DTOs:

// TypeORM entity property decorators
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;
}

Stacking Decorators

Multiple decorators can apply to the same class, method, or parameter. They execute from bottom to top (innermost first):

@UseGuards(AuthGuard)
@UseInterceptors(LoggingInterceptor)
@Get('profile')
getProfile() { ... }

The order matters in some cases. Guards run before interceptors, and both run before the method itself.

TypeScript and Decorator Metadata

NestJS decorators work because TypeScript emits type metadata — information about parameter types and return types — when you compile. NestJS reads this metadata to understand what type to inject into constructors. The tsconfig.json in every NestJS project enables this with two settings:

"emitDecoratorMetadata": true,
"experimentalDecorators": true

These settings are present by default in every NestJS project the CLI creates. You do not need to add them manually.

Decorators Keep Code Clean

Without decorators, you would configure routes, guards, pipes, and response codes through verbose function calls or configuration objects scattered across your code. Decorators consolidate all this information at the point of use — on the class or method itself. The result is code that reads like a structured document: you see the route, the guards, the HTTP method, and the response code all in one glance, without digging through configuration files.

Leave a Comment

Your email address will not be published. Required fields are marked *