NestJS — Enterprise Node.js

Reflection Metadata & Typed Decorators

18 min Lesson 50 of 80

Reflection Metadata & Typed Decorators

Metadata is how NestJS turns decorators into runtime decisions. A decorator can attach roles, feature flags, cache keys, audit labels, or public-route markers; a guard or interceptor can then read that metadata and apply policy consistently.

Core idea

This feature is about controlling how the application is organized and how it behaves at runtime. These are the points a developer should understand before using it in a real project:

  • SetMetadata() works, but Reflector.createDecorator() gives stronger typing and removes string-key mistakes.
  • getAllAndOverride() is ideal when method metadata should replace controller metadata.
  • getAllAndMerge() is useful when class-level and method-level metadata should combine.
  • Metadata belongs to orchestration decisions; do not hide business rules that belong in services.
  • Composed decorators with applyDecorators() keep controllers readable when a route needs guards, roles, OpenAPI metadata, and interceptors together.

Practical example

The following example shows the idea in a practical NestJS project. The goal is not to memorize the snippet, but to understand where it belongs in the architecture:

export const Roles = Reflector.createDecorator<string[]>(); export function AdminEndpoint(summary: string) { return applyDecorators( Roles(['admin']), UseGuards(JwtAuthGuard, RolesGuard), ApiBearerAuth(), ApiOperation({ summary }), ); } @AdminEndpoint('List billing reports') @Get('reports') findReports() { return this.reportsService.findAll(); }
Design note: Typed decorators create a contract between route declarations and framework components. The route stays declarative while the guard or interceptor owns the runtime enforcement.

Production checklist

  • Use typed decorator factories for repeated metadata keys.
  • Choose override vs merge semantics deliberately.
  • Do not create decorators that perform database work directly.
  • Keep composed decorators small enough that their behavior is still obvious at the route.
Rule of thumb: If the feature makes boundaries clearer and tests easier, it is probably the right choice. If it hides dependencies or makes tracing harder, redesign.

Summary

This lesson covers an advanced NestJS area that matters when building enterprise applications. Focus on clear boundaries, testable behavior, and choosing the right tool for the context instead of using every feature everywhere.