Skip to main content
Version: Next

decorate

Overview

The decorate function is a utility that allows you to apply decorators programmatically to classes, methods, properties, and constructor parameters without using the decorator syntax (@decorator). This is particularly useful when:

  1. You can't modify the original class to add decorators
  2. You're working with third-party classes
  3. You want to conditionally apply decorators
  4. You're in an environment where decorator syntax is not available

API Reference

The decorate function has multiple overloads to handle different decorator types:

function decorate(
decorators: ClassDecorator | ClassDecorator[],
target: Function
): void;

function decorate(
decorators: ParameterDecorator | ParameterDecorator[],
target: Function,
parameterIndex: number
): void;

function decorate(
decorators: MethodDecorator | PropertyDecorator | MethodDecorator[] | PropertyDecorator[],
target: Function,
property: string | symbol
): void;

export function decorate(
decorators: ParameterDecorator | ParameterDecorator[],
target: Function,
methodName: string | symbol,
parameterIndex: number,
): void;

Examples

Applying ClassDecorator

Use this to apply class-level decorators like @injectable():

class Katana implements Weapon {
public readonly damage: number = 10;
}

// Apply @injectable decorator using decorate function
decorate(injectable(), Katana);

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);

const katana: Weapon = container.get<Weapon>('Weapon');

Applying ParameterDecorator

Use this to apply decorators to constructor parameters like @inject():

@injectable()
class Warrior {
private readonly weapon: Weapon;

constructor(weapon: Weapon) {
this.weapon = weapon;
}

public fight(): string {
return `Fighting with weapon damage: ${this.weapon.damage.toString()}`;
}
}

// Apply @inject decorator to constructor parameter using decorate function
decorate(inject('Weapon'), Warrior, 0);

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.bind<Warrior>('Warrior').to(Warrior);

const warrior: Warrior = container.get<Warrior>('Warrior');

Applying PropertyDecorator

Use this to apply decorators to class properties like @inject():

@injectable()
class Warrior {
public weapon!: Weapon;

public fight(): string {
return `Fighting with weapon damage: ${this.weapon.damage.toString()}`;
}
}

// Apply @inject decorator to property using decorate function
decorate(inject('Weapon'), Warrior, 'weapon');

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.bind<Warrior>('Warrior').to(Warrior);

const warrior: Warrior = container.get<Warrior>('Warrior');

Applying MethodDecorator

Use this to apply decorators to class methods:

@injectable()
class Katana implements Weapon {
private _damage: number = 10;

public get damage(): number {
return this._damage;
}

public improve(): void {
this._damage += 2;
}
}

// Apply @postConstruct decorator to method using decorate function
decorate(postConstruct(), Katana, 'improve');

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);

const katana: Katana = container.get<Weapon>('Weapon') as Katana;

Use Cases

Working with Third-Party Classes

When you need to make a third-party class injectable but cannot modify its source code:

import { decorate, injectable } from 'inversify';
import { SomeThirdPartyClass } from 'some-library';

// Make the third-party class injectable
decorate(injectable(), SomeThirdPartyClass);

Conditional Decoration

Apply decorators based on runtime conditions:

import { decorate, injectable } from 'inversify';

class MyService {
// Implementation
}

// Conditionally make it injectable
if (process.env.NODE_ENV === 'production') {
decorate(injectable(), MyService);
}

Important Notes

  • The decorate function must be called before the class is used in container bindings
  • For ParameterDecorator, the parameter index is 0-based (first parameter = 0, second = 1, etc.)
  • You can pass either a single decorator or an array of decorators