Decorators Reference
Reference for stage-3 decorator signatures in TypeScript 5+. Each decorator kind has its own context type — sticking to the right shape keeps the compiler happy.
Class decorator
TS
type ClassDecorator<TFunction extends abstract new (...args: any) => any> = (
value: TFunction,
context: ClassDecoratorContext<TFunction>,
) => TFunction | void;
Method decorator
TS
type MethodDecorator<This, Args extends any[], Return> = (
value: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>,
) => ((this: This, ...args: Args) => Return) | void;
Field decorator
TS
type FieldDecorator<This, Value> = (
value: undefined,
context: ClassFieldDecoratorContext<This, Value>,
) => ((this: This, value: Value) => Value) | void;
Getter / setter / accessor
| Decorator type | Context type |
|---|---|
| getter | ClassGetterDecoratorContext<This, Value> |
| setter | ClassSetterDecoratorContext<This, Value> |
| auto-accessor | ClassAccessorDecoratorContext<This, Value> |
Context properties (all kinds)
| Property | Means |
|---|---|
kind | "class" / "method" / "field" / "getter" / … |
name | Member name (string or symbol). |
static | Boolean — is the member static? |
private | Boolean — # private? |
addInitializer(fn) | Schedule code to run when the decorated thing is created. |
metadata | Object for sharing data between decorators (4.1+). |
access | { has, get, set } — type-safe member access. |
Decorator factories
TS
function memoize<TArgs extends unknown[], TRet>(opts: { max: number } = { max: 100 }) {
return function (
target: (...args: TArgs) => TRet,
_ctx: ClassMethodDecoratorContext,
) {
const cache = new Map<string, TRet>();
return function (this: unknown, ...args: TArgs) {
const key = JSON.stringify(args);
if (!cache.has(key)) {
if (cache.size >= opts.max) cache.delete(cache.keys().next().value as string);
cache.set(key, target.apply(this, args));
}
return cache.get(key)!;
};
};
}
class Service {
@memoize({ max: 50 })
expensive(x: number) { /* ... */ return x * x; }
}
Experimental (legacy) decorators
Pre-stage-3 decorators are still around — enable with "experimentalDecorators": true. Common in Angular and older NestJS. Different signatures; not interchangeable with the new ones.
Tip: For new code, prefer stage-3 decorators. They match the future JS spec, integrate with type-aware tooling, and have less weird metadata machinery.
Example
Example
// TS 5 implements Stage-3 decorators.
// Signature shapes:
// ClassDecoratorContext
// ClassMethodDecoratorContext
// ClassFieldDecoratorContext
// ClassGetterDecoratorContext / Setter / Accessor
//
// Legacy decorators still work behind --experimentalDecorators.
console.log('Decorators are functions that wrap class members');
Try it Yourself »
Exercise
Method-decorator context type name.
ctx:
<This, Fn>
PascalCase; one long word.
Discussion
Loading…