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