Reflector helps you read metadata set by custom decorators in NestJS. Custom decorators let you add extra info to classes or methods simply.
Reflector and custom decorators in NestJS
import { SetMetadata } from '@nestjs/common'; export const MyDecorator = (value: any) => SetMetadata('myKey', value); // Using Reflector in a guard or interceptor import { Reflector } from '@nestjs/core'; constructor(private reflector: Reflector) {} const data = this.reflector.get('myKey', context.getHandler());
SetMetadata creates a decorator that attaches data to routes or classes.
Reflector reads that data later, usually inside guards or interceptors.
import { SetMetadata } from '@nestjs/common'; export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
import { Reflector } from '@nestjs/core'; constructor(private reflector: Reflector) {} const roles = this.reflector.get<string[]>('roles', context.getHandler());
This example shows a custom @Roles decorator that sets roles metadata. The RolesGuard uses Reflector to read this metadata and check if the user has any required role before allowing access.
import { Controller, Get, UseGuards, SetMetadata, CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; // Custom decorator to set roles metadata export const Roles = (...roles: string[]) => SetMetadata('roles', roles); // Guard that uses Reflector to check roles @Injectable() class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler()); if (!requiredRoles) { return true; // no roles required } // For demo, pretend user roles come from request const request = context.switchToHttp().getRequest(); const userRoles = request.user?.roles || []; return requiredRoles.some(role => userRoles.includes(role)); } } @Controller('cats') export class CatsController { @Get() @Roles('admin') @UseGuards(RolesGuard) findAll() { return 'This route is restricted to admins'; } }
Always inject Reflector via constructor to access metadata.
Metadata keys should be unique strings to avoid conflicts.
Custom decorators keep your code organized and reusable.
Reflector reads metadata set by custom decorators.
Custom decorators add extra info to routes or classes.
Use them together to control behavior like access or logging.
Practice
Reflector class in NestJS when used with custom decorators?Solution
Step 1: Understand Reflector's role
The Reflector class is designed to read metadata that custom decorators attach to classes or methods.Step 2: Differentiate from other functions
It does not create decorators, change routing, or validate payloads; it only reads metadata.Final Answer:
To read metadata set by custom decorators on classes or methods -> Option AQuick Check:
Reflector reads metadata = D [OK]
- Thinking Reflector creates decorators
- Confusing Reflector with validation tools
- Assuming Reflector changes routing behavior
Solution
Step 1: Recall SetMetadata usage
SetMetadata is the NestJS helper to create decorators that attach metadata with a key and value.Step 2: Check each option
export const Roles = (roles: string[]) => SetMetadata('roles', roles); correctly returns SetMetadata with key 'roles' and the passed roles array. export function Roles(roles: string[]) { return Reflect.metadata('roles', roles); } uses Reflect.metadata which is not standard in NestJS. export const Roles = (roles: string[]) => Reflector.set('roles', roles); incorrectly calls Reflector.set which does not exist. export function Roles() { return SetMetadata('roles'); } calls SetMetadata without value, which is invalid.Final Answer:
export const Roles = (roles: string[]) => SetMetadata('roles', roles); -> Option DQuick Check:
SetMetadata creates decorators with key-value metadata = A [OK]
- Using Reflector to set metadata instead of reading
- Omitting the value argument in SetMetadata
- Using Reflect.metadata instead of SetMetadata
getData method?import { Controller, Get, UseGuards, SetMetadata } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
const Roles = (roles: string[]) => SetMetadata('roles', roles);
@Controller('items')
export class ItemsController {
@Get()
@Roles(['admin'])
getData() {
return 'secret data';
}
}
// In a guard:
const reflector = new Reflector();
const roles = reflector.get<string[]>('roles', ItemsController.prototype.getData);
console.log(roles);Solution
Step 1: Understand metadata retrieval context
Reflector.get requires the target object and the property key (method name as string) to read metadata.Step 2: Analyze the call
The code calls reflector.get with ItemsController.prototype.getData as the second argument, which is a function, not the method name string 'getData'. This causes Reflector to fail to find metadata and return undefined.Final Answer:
undefined -> Option BQuick Check:
Reflector.get needs method name string, else returns undefined [OK]
- Passing method function instead of method name string
- Expecting metadata on class prototype instead of method
- Assuming metadata always returns array
import { SetMetadata } from '@nestjs/common';
function Permissions(permissions: string[]) {
return (target: any, key: string) => {
Reflect.defineMetadata('permissions', permissions, target, key);
};
}
class UserController {
@Permissions(['read'])
getUser() {
return 'user';
}
}Solution
Step 1: Check decorator implementation
The decorator manually calls Reflect.defineMetadata, which works but is not recommended in NestJS.Step 2: Use NestJS helper for consistency
SetMetadata is the standard NestJS helper that wraps Reflect.defineMetadata and ensures compatibility with Reflector and other NestJS internals.Final Answer:
The decorator should use SetMetadata instead of Reflect.defineMetadata -> Option CQuick Check:
Use SetMetadata for custom decorators in NestJS [OK]
- Using Reflect.defineMetadata directly instead of SetMetadata
- Ignoring NestJS decorator conventions
- Misunderstanding decorator parameters
@Roles decorator metadata. Which approach correctly uses Reflector and the custom decorator to achieve this?Solution
Step 1: Understand metadata inheritance
Roles can be set on method or class level. To get effective roles, use Reflector.getAllAndOverride which checks method first, then class.Step 2: Implement guard logic
Retrieve roles with getAllAndOverride, then compare with user's roles to allow or deny access.Final Answer:
Use Reflector.getAllAndOverride('roles', [context.getHandler(), context.getClass()]) to get roles, then check user roles against it -> Option AQuick Check:
getAllAndOverride merges metadata from method and class [OK]
- Ignoring class-level metadata roles
- Trying to set metadata inside guard
- Not using Reflector to read metadata
Ready to prove it?
Pass the test and this pattern moves unknown
