Los decoradores son anotaciones especiales que permiten modificar el comportamiento de clases, propiedades, métodos o parámetros a través de metainformación adicional o sustitución de la implementación.
Generalmente se utilizan para inyección de dependencias, registro, validación, almacenamiento en caché o declaración de metadatos para marcos como Angular.
Ejemplo de un decorador de método simple:
function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const original = descriptor.value; descriptor.value = function(...args: any[]) { console.log(`Llamada: ${propertyKey}(${JSON.stringify(args)})`); return original.apply(this, args); }; } class Example { @Log doSomething(a: number, b: number) { return a + b; } }
Obstáculos:
experimentalDecorators en tsconfig.Pregunta: "¿Es posible tipar los parámetros del decorador de tal manera que se garantice el tipo del método al que se aplica?"
Respuesta: En la mayoría de los casos, la tipificación no es posible en la etapa de aplicación del decorador debido a la naturaleza dinámica de la metaprogramación. Sin embargo, a través de generics y validaciones adicionales en tiempo de ejecución, se puede agregar validación, pero el compilador de TypeScript no puede garantizarlo en la etapa de declaración de la estructura.
Ejemplo:
function MyDecorator(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<number>) { /* ... */ } // El compilador no garantiza que el método devuelva un número
Historia
En un proyecto con muchos decoradores en servicios, se olvidaron del orden de aplicación: los decoradores de propiedad se aplicaron antes que todos los parámetros, resultando en la pérdida de metadatos de Inyección y la imposibilidad de resolver las dependencias en tiempo de ejecución.
Historia
Los desarrolladores decidieron aplicar decoradores a funciones normales, en lugar de métodos de clase, y se sorprendieron por los errores de compilación y la falta de efecto en tiempo de ejecución. En la especificación de TypeScript, los decoradores solo se aplican a clases y sus miembros.
Historia
Después de actualizar las versiones de TypeScript y las configuraciones experimentales, se rompió todo el mecanismo de decoradores en un contenedor DI personalizado: resultó que la nueva versión requería el soporte explícito de Reflect-metadata, de lo contrario, toda la metainformación se perdía.