← Back to TypeScript Course | Chapter 10: Decorators | Lesson 5 of 7

Parameter Decorators

Parameter decorators belong to TypeScript's legacy experimental decorator system rather than the modern standard decorator model. They can observe method or constructor parameters, but they cannot replace a parameter or change its value directly.

Legacy Parameter Decorator Signature

The legacy (experimentalDecorators) parameter decorator signature receives the target object, the method name the parameter belongs to, and the parameter's numeric index within that method's argument list.

Example: Legacy Parameter Decorator Signature

typescript
function logParam(target: any, methodName: string, index: number) {
  console.log(`Parameter ${index} of ${methodName} decorated`);
}
class Service {
  greet(@logParam name: string) {
    return "Hello " + name;
  }
}
new Service().greet("Ravi");

Parameter Indexes

Because parameter decorators only get an index rather than a name, tooling built on them (like dependency-injection frameworks) typically has to also read the method's declared parameter types via reflection to make sense of that index.

Example: Parameter Indexes

typescript
function inject(target: any, methodName: string, index: number) {
  console.log(`Injecting into parameter index ${index}`);
}
class Controller {
  handle(@inject req: any, res: any) {
    return "handled";
  }
}
new Controller().handle({}, {});

Recording Parameter Metadata

A common use is recording which parameter index should receive an injected value in a metadata map, which some other part of the code (usually the method decorator) later reads when the method is actually invoked.

Example: Recording Parameter Metadata

typescript
const injectionMap = new Map<string, number[]>();
function injectable(target: any, methodName: string, index: number) {
  const existing = injectionMap.get(methodName) ?? [];
  existing.push(index);
  injectionMap.set(methodName, existing);
}
class Repo {
  find(@injectable id: number) {
    return id;
  }
}
new Repo();
console.log(injectionMap);

Parameter Decorator Limitations

Parameter decorators cannot change what value gets passed in or intercept the call directly — they can only attach metadata alongside the parameter, so any real behavior change has to happen in a paired method or class decorator.

Example: Parameter Decorator Limitations

typescript
function noteOnly(target: any, methodName: string, index: number) {
  // Cannot change the value passed in -- only records metadata.
  console.log(`Noted parameter ${index}, value unaffected`);
}
class Logger {
  log(@noteOnly message: string) {
    console.log(message);
  }
}
new Logger().log("hello");

Modern Decorator Alternative

TypeScript's newer standard decorators proposal drops parameter decorators entirely in favor of attaching validation logic directly inside method decorators, so legacy parameter decorators are mostly seen in older dependency-injection codebases.

Example: Modern Decorator Alternative

typescript
// Legacy: parameter decorators (experimentalDecorators)
// Modern: validation moves into the method decorator itself
function validateArgs(target: any, context: ClassMethodDecoratorContext) {
  return function (this: any, ...args: any[]) {
    console.log("Validating all args together:", args);
    return target.call(this, ...args);
  };
}
class Service {
  @validateArgs
  process(id: number) {
    return id;
  }
}
new Service().process(1);
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.