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);
}
}
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) { /* ... */ }
}
Enable in tsconfig
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
Decorators, DI patterns, and clean architecture are part of the advanced TypeScript patterns in the Ship Fast Skill Pack.
Top comments (0)