Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

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.
const decoratorExpression = (value, context) => {
  // decorator logic
};

// Applied to a named class declaration
@decoratorExpression
class TargetClass {
  // class body
}

// Applied to an anonymous class declaration
export default @decoratorExpression class {
  // class body
}

The Decorator Signature

A class decorator function is invoked with two parameters: value and context.
function classDecorator(value, context) {
  // value: The target class constructor
  // context: Metadata and utility functions
  
  // Optionally return a new constructor to replace the original
}

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: "class",
  name: "TargetClass", // String name, or undefined for anonymous classes
  metadata: {},        // Plain object for sharing metadata
  addInitializer: function(initializerFn) { /* ... */ }
}
  • 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:
function InterceptClass(value, context) {
  // Ensure the decorator is only applied to classes
  if (context.kind !== "class") return;

  // Return a new constructor that extends the original 'value'
  return class extends value {
    constructor(...args) {
      super(...args);
      // The original class is now wrapped
    }
  };
}

@InterceptClass
class StandardClass {
  constructor(param) {
    this.param = param;
  }
}

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.
function ConfigurableDecorator(configParam) {
  // The outer function evaluates first and captures 'configParam'
  
  return function actualDecorator(value, context) {
    // The inner function is applied to the class
    if (configParam === true) {
      // Mutate or replace 'value'
    }
  };
}

@ConfigurableDecorator(true)
class AnotherClass {}
Master JavaScript with Deep Grasping Methodology!Learn More