TC39 Decorators Reference

Stage 3 JavaScript class, method, accessor and field decorator syntax and hooks.

Reference for the TC39 Stage 3 decorators proposal covering class, method, getter, setter, auto-accessor and field decorators, the context object passed to each, and the addInitializer hook.

How are Stage 3 decorators different from the old experimental ones?

The legacy TypeScript and Babel decorators received a property descriptor and could mutate it directly. The Stage 3 decorators instead receive the value being decorated plus a structured context object, and they wire up behaviour by returning a replacement value or calling context.addInitializer. The shapes are not compatible.

What TC39 decorators are

Decorators are a Stage 3 JavaScript proposal for annotating and modifying classes and their members with reusable @decorator syntax. Unlike the older experimental decorators that mutated a property descriptor, the modern proposal hands each decorator the value being decorated plus a structured context object, and you opt into behaviour by returning a replacement value or calling context.addInitializer. This makes decorators predictable and composable.

How it works

A decorator is a function called once, at class-definition time, with two arguments: (value, context). The value depends on the target — a function for methods, the class itself for class decorators, undefined for fields — and the context always carries kind, name, static, private, and an addInitializer hook (plus an access object for members). What you may return also depends on the target:

function logged(value, context) {
  if (context.kind === "method") {
    return function (...args) {
      console.log(`calling ${String(context.name)}`);
      return value.apply(this, args);
    };
  }
}

The reference below lists each target with the value it receives, the relevant context fields, and the legal return values.

Tips and notes

Decorators evaluate outermost-last: in @a @b method(), b is applied before a, and a wraps b’s result. Field decorators return an initializer (value transformer), not a replacement value. The accessor keyword creates an auto-accessor whose decorator returns an object with get, set, and/or init. Use addInitializer for side-effects like method binding or metadata registration — that is the only place this refers to the instance.