Creating and Using NestJS Custom Decorators

Learn how to create and use custom decorators in NestJS.

overview

NestJS allows you to take advantage of custom decorators to extract specific data or add specific metadata to classes and methods. Custom decorators are very useful for retrieving specific data from the request object or for simplifying things like dependency injection.

How to create a custom decorator

To create a custom decorator, first create a new decorator using the createParamDecorator function. Below is an example of creating a custom decorator to retrieve the authenticated user’s information from the request.

Since there is a convenient CLI, we will use it to create it.

nest g d users/decorator/user

/src/users/decorators/user/user.decorator.ts

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.body.user;
  },
);

The code above creates a custom decorator named User. This decorator gets an HTTP request object from the execution context and returns its user information.

How to use custom decorators

To make use of your custom decorator, apply it to a method parameter. Below is an example that utilizes the custom decorator we created.

/src/users/users.controller.ts

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  HttpException,
  HttpStatus,
  Use filters,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { ForbiddenException } from './exceptions/forbidden.exception';
import { HttpExceptionFilter } from './filters/http-exception/http-exception.filter';
import { User } from './decorator/user/user.decorator';

@Controller('users')
@UseFilters(new HttpExceptionFilter())
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  getUsers(): User[] {
    return this.usersService.getUsers();
  }

  @Post()
  addUser(@Body() name: string): void {
    this.usersService.addUser(name);
  }

  @Put(':id')
  putUser(@Param('id') id: number, @Body('name') name: string): void {
    this.usersService.putUser(id, name);
  }

  @Delete(':id')
  deleteUser(@Param('id') id: number): void {
    this.usersService.deleteUser(id);
  }
  @Get('throw')
  getException(): string {
    throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
  }
  @Get('custom_throw')
  getCustomException(): string {
    throw new ForbiddenException();
  }
  @Post('custom_decorator')
  getCustomDecorator(@User() user: User) {
    return user;
  }
}

The code above uses the @User() decorator in the getProfile method of the ProfileController. This will automatically extract the user information from the request and inject it into the user parameter of the getProfile method.

test

curl -X POST http://localhost:3000/users/custom_decorator -H 'Content-Type: application/json' -d '{"user": {"name": "test"}}'

summary

NestJS allows you to take advantage of custom decorators to extract specific data from the request object or add specific metadata to classes and methods. This allows for more flexible coding and simplified processing.