Custom Decorators in NestJS: A Practical Guide

Agarwal Peeyush
3 min readMar 29, 2024

--

Introduction:

Decorators are essential for providing metadata to classes, methods, properties, and parameters in the world of TypeScript and contemporary JavaScript frameworks such as NestJS. Even while the decorators provided by libraries and frameworks are strong, there may be occasions when you need to build your own to customize features to meet your unique needs. We’ll examine the idea of custom decorators in NestJS, comprehend their operation, and examine real-world applications with examples in this blog article.

Photo by Blake Connally on Unsplash

Understanding Custom Decorators:

Decorators are functions in NestJS that can be added to classes, methods, or properties to change or add to their functionality. Developers can apply reusable logic to various areas of their program by encapsulating it in custom decorators. Decorators can be applied to controllers, services, or any other parts of a NestJS application. They are made using the TypeScript decorators syntax.

Example of Custom Decorator:

Let’s consider a scenario where we want to create a custom decorator to log the execution time of a specific method within a service. We’ll create a decorator named LogExecutionTime that logs the time taken by the method to execute.

// log-execution-time.decorator.ts

import { Logger } from '@nestjs/common';

export function LogExecutionTime(): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const startTime = Date.now();
const result = await originalMethod.apply(this, args);
const endTime = Date.now();
const executionTime = endTime - startTime;
Logger.log(`Method ${propertyKey} execution time: ${executionTime}ms`, target.constructor.name);
return result;
};
return descriptor;
};
}

In this example, we define a function named LogExecutionTime that returns a method decorator. Inside the decorator function, we intercept the execution of the original method, calculate the execution time, and log it using NestJS Logger.

Using Custom Decorator:

Now, let’s see how we can use the LogExecutionTime decorator in a service method.

// example.service.ts

import { Injectable } from '@nestjs/common';
import { LogExecutionTime } from './log-execution-time.decorator';

@Injectable()
export class ExampleService {

@LogExecutionTime()
async performTask(): Promise<void> {
// Simulate a delay
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Task completed!');
}
}

In this service class, we apply the @LogExecutionTime() decorator to the performTask() method. Now, whenever performTask() is called, it will log the execution time to the console.

Use Cases of Custom Decorators:

  1. Rate Limiting: Implement decorators to enforce rate limits on API endpoints to prevent abuse or excessive usage.
  2. Validation: Define decorators to validate input parameters or request payloads before processing them.
  3. Logging: Use decorators to log method executions, errors, or other important events within your application.
  4. Caching: Create decorators to cache the results of expensive method calls and improve performance.
  5. Authorization: Implement custom decorators to handle authentication and authorization logic for API endpoints.

Conclusion:

the NestJS framework has an excellent feature called custom decorators that let programmers expand the usability of their apps in a reusable and modular manner. Developers can encapsulate common patterns and actions by writing custom decorators, which results in cleaner, more maintainable code. Gaining proficiency in generating and utilizing personalized decorators allows you to expand the functionalities of your the NestJS framework apps.

Happy Learning! Feel free to connect with me over LinkedIn!

--

--

No responses yet