DEV Community

Atlas Whoff
Atlas Whoff

Posted on

TypeScript Decorators: Clean Metaprogramming Patterns

TypeScript Decorators: Clean Metaprogramming Patterns

Decorators let you attach behavior to classes, methods, and properties without modifying their internals. They power NestJS, TypeORM, and Angular.

Method Decorators

function Retry(attempts: number) {
  return function (target: any, key: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = async function (...args: any[]) {
      let lastError: Error;
      for (let i = 0; i < attempts; i++) {
        try { return await original.apply(this, args); }
        catch (err) {
          lastError = err as Error;
          if (i < attempts - 1)
            await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
        }
      }
      throw lastError!;
    };
    return descriptor;
  };
}

class PaymentService {
  @Retry(3)  // Automatically retries with exponential backoff
  async chargeCard(amount: number) {
    return await stripeClient.charge(amount);
  }
}
Enter fullscreen mode Exit fullscreen mode

Logging Decorator

function Log(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = async function (...args: any[]) {
    const start = Date.now();
    try {
      const result = await original.apply(this, args);
      console.log(`[${key}] completed in ${Date.now() - start}ms`);
      return result;
    } catch (err) {
      console.error(`[${key}] failed:`, err);
      throw err;
    }
  };
}

class OrderService {
  @Log
  async createOrder(data: CreateOrderDto) { /* ... */ }
}
Enter fullscreen mode Exit fullscreen mode

Enable in tsconfig

{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
Enter fullscreen mode Exit fullscreen mode

Decorators, DI patterns, and clean architecture are part of the advanced TypeScript patterns in the Ship Fast Skill Pack.

Top comments (0)