ESNext Decorators – class enhancements in 2024
The class decorator syntax in JavaScript has been evolving for some time and as of 2024 the JavaScript Decorators proposal has matured to Stage 3 (or perhaps Stage 4 depending on the time). This opens up pattern changes for metadata, dependency injection, logging cross-cutting concerns, etc.
What are decorators
Decorators are special declarations prefixed by @ that you place on classes, methods, accessors or fields to wrap or enhance behaviour:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function log(target, key, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${key} with `, args);
return original.apply(this, args);
};
return descriptor;
}
class MyClass {
@log
hello(name) {
return `Hello, ${name}`;
}
}
Where the proposal stands
- The current spec draft allows class, method, field and accessor decorators.
- For now you’ll need a transpiler like Babel or TypeScript with experimental flag enabled.
- Many frameworks (Angular, NestJS) already use decorator-style syntax.
Why it matters
- Brings nicer syntax for cross-cutting concerns (logging, authorization).
- Enables better metadata reflection via decorators.
- Aligns JavaScript/TypeScript patterns more with other languages.
How to use it now
- In your
babel.config.js:
1
2
3
4
5
6
7
module.exports = {
presets: ['@babel/preset-env'],
plugins: [
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
],
};
- In TypeScript
tsconfig.json:
1
2
3
4
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
- Simple decorator:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function memo(target: any, key: string, descriptor: PropertyDescriptor) {
const orig = descriptor.value;
const cache = new Map();
descriptor.value = function(...args: any[]) {
const keyArg = JSON.stringify(args);
if(cache.has(keyArg)) return cache.get(keyArg);
const result = orig.apply(this, args);
cache.set(keyArg, result);
return result;
};
return descriptor;
}
class Fib {
@memo
calc(n: number): number {
return n < 2 ? n : this.calc(n-1) + this.calc(n-2);
}
}
Limitations & caveats
- Decorators are syntactic sugar.
- Legacy vs new proposal differences.
- Overuse can harm readability.
Summary
Decorators are a powerful addition to JavaScript/TypeScript for 2024.