Skip to main content
A class decorator is a higher-order function applied to a class declaration that intercepts the class definition process. It receives the class constructor and a context object as arguments, allowing developers to mutate the class, append metadata, or entirely replace the constructor function before the class is ever instantiated. According to the ECMAScript Stage 3 Decorators specification, decorators are strictly applied to class declarations. They are forbidden on class expressions due to grammar ambiguities, though they can be applied to anonymous class declarations via default exports.

The Decorator Signature

A class decorator function is invoked with two parameters: value and context.

1. The value Parameter

For a class decorator, the value argument is the class constructor function itself. The decorator can mutate the constructor, modify its prototype, or wrap it in a subclass.

2. The context Parameter

The context is an object providing metadata about the decorated element and utility functions. For class decorators, the context object conforms to the following structure:
  • kind: A string literal indicating the type of syntax being decorated. For class decorators, this is strictly "class".
  • name: The string identifier of the class. If the decorator is applied to an anonymous class declaration, this property evaluates to undefined.
  • metadata: A plain JavaScript object used to store and share metadata between decorators applied to the same class or its members.
  • addInitializer: A method that accepts a callback function. This callback is executed immediately after the class is fully defined, allowing for static initialization logic.

Execution Flow and Evaluation

Decorators are evaluated and applied at definition time, not at instantiation time. The execution follows a strict sequence:
  1. Evaluation: The expression following the @ symbol is evaluated to resolve the decorator function.
  2. Application: The resolved function is invoked, passing the class constructor and the context object.
  3. Replacement:
    • If the decorator returns a valid constructor function (e.g., a new class or function), the JavaScript engine replaces the original class definition with this returned constructor.
    • If the decorator returns undefined (either explicitly or implicitly by lacking a return statement), the original class constructor is retained.
    • If the decorator returns any other type of value (such as a primitive or a non-callable object), the JavaScript engine will throw a TypeError during the class definition process. (Note: Returning a callable non-constructor, such as an arrow function, satisfies the definition-time IsCallable check but will throw a TypeError later if instantiation via new is attempted).

Mechanical Example

The following demonstrates the mechanics of intercepting a class definition and replacing it with an anonymous subclass, strictly illustrating the syntax and execution flow:

Decorator Factories

Because the @ syntax requires an expression that evaluates to a function, decorators are frequently implemented as closures (factories). This allows the decorator to accept arguments during evaluation, which are then captured in the lexical scope of the actual decorator function.
Tired of Poor JavaScript Skills? Fix That With Deep Grasping!Learn More