Sijin T V
Sijin T V A passionate Software Engineer who contributes to the wonders happenning on the internet

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

  1. 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 }],
  ],
};
  1. In TypeScript tsconfig.json:
1
2
3
4
{
  "experimentalDecorators": true,
  "emitDecoratorMetadata": true
}
  1. 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.

comments powered by Disqus