DEV Community

Dharan Ganesan
Dharan Ganesan

Posted on

2 1 2

Day 44: Decorators

In this article, we'll take a dive into decorators in TypeScript, explore their types, and provide practical examples to help you harness their full potential.

What Are Decorators? 🎨

At their core, decorators are simply functions that are applied to classes, methods, properties, or parameters using the @ symbol. They can be used for various purposes, including:

  1. Logging and debugging: Adding logging statements before and after method execution.
  2. Validation: Checking the validity of inputs or outputs.
  3. Authorization: Controlling access to certain methods or routes.
  4. Memoization: Caching the results of expensive operations.
  5. Dependency Injection: Automatically injecting dependencies into classes.
  6. Metadata Collection: Storing additional information about classes or properties.

Class Decorators 🏛️

Class decorators are applied to classes. They receive the class constructor as their only parameter and can be used to modify the class or add metadata to it.

function MyDecorator(target: Function) {
  console.log('Class decorator called on', target);
}

@MyDecorator
class MyClass {
  constructor() {
    console.log('MyClass constructor');
  }
}

// Output:
// Class decorator called on [Function: MyClass]
// MyClass constructor
Enter fullscreen mode Exit fullscreen mode

Method Decorators 🛠️

Method decorators are applied to methods within a class. They receive three parameters: the target class prototype, the method name, and a property descriptor.

function LogMethod(target: Object, key: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${key} with arguments: ${args}`);
    const result = originalMethod.apply(this, args);
    console.log(`${key} returned: ${result}`);
    return result;
  };

  return descriptor;
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);

// Output:
// Calling add with arguments: 2,3
// add returned: 5
Enter fullscreen mode Exit fullscreen mode

Property Decorators 🏠

Property decorators are used to modify properties within a class. They receive two parameters: the target class prototype and the property name.

function Validate(target: any, key: string) {
  let value = target[key];

  const getter = () => value;

  const setter = (newValue: any) => {
    if (typeof newValue !== 'number' || newValue < 0) {
      throw new Error('Invalid value');
    }
    value = newValue;
  };

  Object.defineProperty(target, key, {
    get: getter,
    set: setter,
  });
}

class Product {
  @Validate
  price: number;

  constructor(price: number) {
    this.price = price;
  }
}

const product = new Product(50);
product.price = -10; // Throws an error

// Output:
// Error: Invalid value
Enter fullscreen mode Exit fullscreen mode

Parameter Decorators 🎯

Parameter decorators are applied to parameters of methods within a class. They receive three parameters: the target class prototype, the method name, and the index of the parameter.

const Injectable = (): ParameterDecorator => {
  return (target: any, key: string | symbol, index: number) => {
    // Register the dependency injection here
    console.log(`Injecting parameter at index ${index} in method ${key}`);
  };
};

class UserService {
  constructor(private readonly logger: Logger) {}

  @Injectable()
  log(message: string) {
    this.logger.log(message);
  }
}

const logger = new Logger();
const userService = new UserService(logger);
userService.log('Hello, Decorators!');

// Output:
// Injecting parameter at index 0 in method log
// Hello, Decorators!
Enter fullscreen mode Exit fullscreen mode

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more