Cuándo crear decorators personalizados en TypeScript
Los decorators te ahorran código repetitivo y hacen tu arquitectura declarativa. Creá uno cuando necesites: aplicar la misma lógica a múltiples clases/métodos (logging, validación, cache), modificar comportamiento sin tocar la implementación, o agregar metadata para reflexión en runtime. Ejemplo clásico: @Authorize('admin') es más limpio que chequear roles en cada endpoint. También son útiles para cross-cutting concerns (seguridad, monitoreo, transacciones) que no pertenecen a la lógica de negocio. Si estás copiando el mismo try-catch o timer en 10 métodos, necesitás un decorator.
Tipos de decorators y sus casos de uso
Class decorators: Modifican constructores, útiles para DI o registrar clases (@Injectable, @Entity). Method decorators: Wrappean métodos, ideales para logging, cache, validación (@Log, @Cache). Property decorators: Modifican propiedades, se usan para metadata o transformaciones (@Column, @Expose). Parameter decorators: Marcan parámetros, comunes en frameworks web (@Body, @Param). NestJS y Angular usan todos los tipos; TypeORM se enfoca en class y property; en librerías custom, method decorators son los más versátiles.
Cómo nombrar decorators para que sean autodocumentados
Usá verbos o estados claros: @Validate dice qué hace, @IsEmail qué verifica, @Authorized qué requiere. Evitá nombres genéricos como @Do o @Handle. Si el decorator recibe parámetros, el nombre debe sugerir qué espera: @Cache(60) (TTL en segundos), @Roles('admin', 'editor') (strings de roles). Prefijos comunes: Is- para validaciones booleanas, Use- para aplicar middleware, Before/After para hooks de lifecycle. Consistencia dentro del proyecto: si usás @LogStart, no uses @TraceEnd para el par; mejor @LogEnd.
Errores comunes al implementar decorators
No preservar metadata: Algunos decorators sobreescriben metadata existente; usá Reflect.defineMetadata con merge. No bindear this: Si el decorator wrappea un método, perdés el contexto de clase; usá arrow functions o .bind(this). Ejecución en build time vs runtime: Decorators se ejecutan al declarar la clase, no al instanciarla; para lógica dinámica, retorná una función. No tipar parámetros: @Custom(options: any) es trampa; definí interfaces claras. Olvidar experimentalDecorators: En tsconfig.json debe estar en true. No documentar comportamiento: Un decorator sin docstring es una caja negra.