Los decoradores en TypeScript son una característica poderosa que permite modificar el comportamiento de clases, métodos, propiedades y parámetros. Los decoradores son una forma de metaprogramación que se puede utilizar para añadir anotaciones y una lógica predefinida a las estructuras de código.
¿Qué son los Decoradores?
Un decorador es una función especial que se puede aplicar a una clase, método, accesor, propiedad o parámetro. Los decoradores se definen con el símbolo @ seguido del nombre del decorador y se colocan justo antes de la declaración que desean modificar.
Tipos de Decoradores
- Decoradores de Clase: Se aplican a una clase.
- Decoradores de Método: Se aplican a un método de una clase.
- Decoradores de Accesor: Se aplican a un accesor (getter o setter) de una clase.
- Decoradores de Propiedad: Se aplican a una propiedad de una clase.
- Decoradores de Parámetro: Se aplican a un parámetro de un método de una clase.
Ejemplo Básico de Decorador de Clase
Vamos a empezar con un ejemplo simple de un decorador de clase. Este decorador añadirá una propiedad estática a la clase.
function addStaticProperty(constructor: Function) {
constructor.prototype.staticProperty = "I am a static property";
}
@addStaticProperty
class MyClass {
constructor() {
console.log("MyClass instance created");
}
}
const myInstance = new MyClass();
console.log((myInstance as any).staticProperty); // Output: I am a static propertyExplicación
- Definición del Decorador:
addStaticPropertyes una función que toma el constructor de la clase como argumento y añade una propiedad estática a su prototipo. - Aplicación del Decorador: El decorador
@addStaticPropertyse aplica a la claseMyClass. - Uso de la Clase: Al crear una instancia de
MyClass, podemos acceder a la propiedad estática añadida por el decorador.
Decoradores de Método
Los decoradores de método se utilizan para modificar el comportamiento de los métodos de una clase. Vamos a crear un decorador que loguea el tiempo de ejecución de un método.
function logExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const end = performance.now();
console.log(`Execution time of ${propertyKey}: ${end - start}ms`);
return result;
};
return descriptor;
}
class Example {
@logExecutionTime
compute() {
// Simulate a time-consuming task
for (let i = 0; i < 1e6; i++) {}
}
}
const example = new Example();
example.compute(); // Output: Execution time of compute: XmsExplicación
- Definición del Decorador:
logExecutionTimees una función que toma el objeto objetivo (target), la clave de la propiedad (propertyKey) y el descriptor del método (descriptor). - Modificación del Método: El decorador reemplaza el método original con una nueva función que mide el tiempo de ejecución y luego llama al método original.
- Aplicación del Decorador: El decorador
@logExecutionTimese aplica al métodocomputede la claseExample.
Decoradores de Propiedad
Los decoradores de propiedad se utilizan para modificar las propiedades de una clase. Vamos a crear un decorador que convierte una propiedad en solo lectura.
function readonly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
writable: false
});
}
class Person {
@readonly
name: string;
constructor(name: string) {
this.name = name;
}
}
const person = new Person("John");
person.name = "Doe"; // Error: Cannot assign to read only property 'name'Explicación
- Definición del Decorador:
readonlyes una función que toma el objeto objetivo (target) y la clave de la propiedad (propertyKey). - Modificación de la Propiedad: El decorador utiliza
Object.definePropertypara hacer que la propiedad sea de solo lectura. - Aplicación del Decorador: El decorador
@readonlyse aplica a la propiedadnamede la clasePerson.
Ejercicio Práctico
Ejercicio
Crea un decorador de método llamado logArguments que registre los argumentos pasados a un método cada vez que se llame.
function logArguments(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
// Tu código aquí
}
class Calculator {
@logArguments
add(a: number, b: number): number {
return a + b;
}
}
const calculator = new Calculator();
calculator.add(2, 3); // Output: Arguments for add: [2, 3]Solución
function logArguments(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Arguments for ${propertyKey}: ${JSON.stringify(args)}`);
return originalMethod.apply(this, args);
};
return descriptor;
}
class Calculator {
@logArguments
add(a: number, b: number): number {
return a + b;
}
}
const calculator = new Calculator();
calculator.add(2, 3); // Output: Arguments for add: [2, 3]Explicación
- Definición del Decorador:
logArgumentses una función que toma el objeto objetivo (target), la clave de la propiedad (propertyKey) y el descriptor del método (descriptor). - Modificación del Método: El decorador reemplaza el método original con una nueva función que registra los argumentos y luego llama al método original.
- Aplicación del Decorador: El decorador
@logArgumentsse aplica al métodoaddde la claseCalculator.
Conclusión
Los decoradores en TypeScript son una herramienta poderosa para modificar y extender el comportamiento de clases, métodos, propiedades y parámetros. En esta sección, hemos cubierto los conceptos básicos de los decoradores y hemos visto ejemplos prácticos de cómo se pueden utilizar. Con esta base, estarás preparado para explorar y aplicar decoradores en tus propios proyectos.
En el siguiente módulo, profundizaremos en la programación asíncrona con TypeScript, comenzando con las promesas.
Curso de TypeScript
Módulo 1: Introducción a TypeScript
- ¿Qué es TypeScript?
- Configuración del Entorno de TypeScript
- Tipos Básicos
- Anotaciones de Tipo
- Compilando TypeScript
Módulo 2: Trabajando con Tipos
Módulo 3: Tipos Avanzados
Módulo 4: Funciones y Módulos
- Tipos de Función
- Parámetros Opcionales y Predeterminados
- Parámetros Rest
- Módulos y Espacios de Nombres
- Decoradores
Módulo 5: Programación Asíncrona
Módulo 6: Herramientas y Mejores Prácticas
- Linting y Formateo
- Pruebas de Código TypeScript
- TypeScript con Webpack
- TypeScript con React
- Mejores Prácticas
