### Custom route decorators Nest is built around a language feature called **decorators**. Decorators are a well-known concept in a lot of commonly used programming languages, but in the JavaScript world, they're still relatively new. In order to better understand how decorators work, we recommend reading [this article](https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841). Here's a simple definition:
An ES2016 decorator is an expression which returns a function and can take a target, name and property descriptor as arguments. You apply it by prefixing the decorator with an @ character and placing this at the very top of what you are trying to decorate. Decorators can be defined for either a class, a method or a property.
#### Param decorators Nest provides a set of useful **param decorators** that you can use together with the HTTP route handlers. Below is a list of the provided decorators and the plain Express (or Fastify) objects they represent
@Request(), @Req() req
@Response(), @Res() res
@Next() next
@Session() req.session
@Param(param?: string) req.params / req.params[param]
@Body(param?: string) req.body / req.body[param]
@Query(param?: string) req.query / req.query[param]
@Headers(param?: string) req.headers / req.headers[param]
@Ip() req.ip
@HostParam() req.hosts
Additionally, you can create your own **custom decorators**. Why is this useful? In the node.js world, it's common practice to attach properties to the **request** object. Then you manually extract them in each route handler, using code like the following: ```typescript const user = req.user; ``` In order to make your code more readable and transparent, you can create a `@User()` decorator and reuse it across all of your controllers. ```typescript @@filename(user.decorator) import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const User = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; }, ); ``` Then, you can simply use it wherever it fits your requirements. ```typescript @@filename() @Get() async findOne(@User() user: UserEntity) { console.log(user); } @@switch @Get() @Bind(User()) async findOne(user) { console.log(user); } ``` #### Passing data When the behavior of your decorator depends on some conditions, you can use the `data` parameter to pass an argument to the decorator's factory function. One use case for this is a custom decorator that extracts properties from the request object by key. Let's assume, for example, that our authentication layer validates requests and attaches a user entity to the request object. The user entity for an authenticated request might look like: ```json { "id": 101, "firstName": "Alan", "lastName": "Turing", "email": "alan@email.com", "roles": ["admin"] } ``` Let's define a decorator that takes a property name as key, and returns the associated value if it exists (or undefined if it doesn't exist, or if the `user` object has not been created). ```typescript @@filename(user.decorator) import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const User = createParamDecorator( (data: string, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); const user = request.user; return data ? user?.[data] : user; }, ); @@switch import { createParamDecorator } from '@nestjs/common'; export const User = createParamDecorator((data, ctx) => { const request = ctx.switchToHttp().getRequest(); const user = request.user; return data ? user && user[data] : user; }); ``` Here's how you could then access a particular property via the `@User()` decorator in the controller: ```typescript @@filename() @Get() async findOne(@User('firstName') firstName: string) { console.log(`Hello ${firstName}`); } @@switch @Get() @Bind(User('firstName')) async findOne(firstName) { console.log(`Hello ${firstName}`); } ``` You can use this same decorator with different keys to access different properties. If the `user` object is deep or complex, this can make for easier and more readable request handler implementations. > info **Hint** For TypeScript users, note that `createParamDecorator()` is a generic. This means you can explicitly enforce type safety, for example `createParamDecorator((data, ctx) => ...)`. Alternatively, specify a parameter type in the factory function, for example `createParamDecorator((data: string, ctx) => ...)`. If you omit both, the type for `data` will be `any`. #### Working with pipes Nest treats custom param decorators in the same fashion as the built-in ones (`@Body()`, `@Param()` and `@Query()`). This means that pipes are executed for the custom annotated parameters as well (in our examples, the `user` argument). Moreover, you can apply the pipe directly to the custom decorator: ```typescript @@filename() @Get() async findOne( @User(new ValidationPipe({ validateCustomDecorators: true })) user: UserEntity, ) { console.log(user); } @@switch @Get() @Bind(User(new ValidationPipe({ validateCustomDecorators: true }))) async findOne(user) { console.log(user); } ``` > info **Hint** Note that `validateCustomDecorators` option must be set to true. `ValidationPipe` does not validate arguments annotated with the custom decorators by default. #### Decorator composition Nest provides a helper method to compose multiple decorators. For example, suppose you want to combine all decorators related to authentication into a single decorator. This could be done with the following construction: ```typescript @@filename(auth.decorator) import { applyDecorators } from '@nestjs/common'; export function Auth(...roles: Role[]) { return applyDecorators( SetMetadata('roles', roles), UseGuards(AuthGuard, RolesGuard), ApiBearerAuth(), ApiUnauthorizedResponse({ description: 'Unauthorized' }), ); } @@switch import { applyDecorators } from '@nestjs/common'; export function Auth(...roles) { return applyDecorators( SetMetadata('roles', roles), UseGuards(AuthGuard, RolesGuard), ApiBearerAuth(), ApiUnauthorizedResponse({ description: 'Unauthorized' }), ); } ``` You can then use this custom `@Auth()` decorator as follows: ```typescript @Get('users') @Auth('admin') findAllUsers() {} ``` This has the effect of applying all four decorators with a single declaration. > warning **Warning** The `@ApiHideProperty()` decorator from the `@nestjs/swagger` package is not composable and won't work properly with the `applyDecorators` function.