Cómo usar decoradores de propiedades en TypeScript con un ejemplo real

En mi artículo anterior hablé sobre decoradores de clases en TypeScript. Hoy es momento de ver los decoradores de propiedades: cómo definirlos y usarlos para escribir código limpio y ordenado.
Qué es un decorador de propiedad
Un decorador de propiedad es una función que se aplica a la declaración de una propiedad en nuestras clases.
Recibe como parámetros la función constructora de la clase (o su prototipo) y el nombre de la propiedad. Con esta información podemos hacer cosas muy interesantes, como cambiar la definición por defecto, modificar la instancia de nuestro objeto, agregar nuevas propiedades o cambiar datos.
class User {
@MyDecorator
password: string;
}Cómo crear mi propio decorador de propiedad
Voy a construir el decorador de propiedad Min, que verifica si una propiedad cumple con una longitud mínima. Si no la cumple, la instancia del objeto tendrá una nueva propiedad errors con un mensaje.
Te lo explicaré paso a paso, o puedes avanzar directamente para ver el código completo. ¡Vamos a ello!
1. Declarar la función Min como decorador
El decorador es una función. Como vamos a usar una fábrica (decorator factory), la función Min recibe el número límite y devuelve otra función que espera el objeto (target) y el nombre de la propiedad (propertyKey).
function Min(limit: number) {
return function(target: Object, propertyKey: string) {2. Definir funciones para el getter y el setter
Necesitamos definir dos funciones para controlar cuándo se lee o se asigna el valor de la propiedad con el decorador.
El getter devuelve el valor de la propiedad:
let value : string;
// Getter de la propiedad para devolver el valor
const getter = function() {
return value;
};El setter recibe el nuevo valor asignado a la propiedad y se encarga de la validación:
const setter = function(newVal: string) {
if(newVal.length < limit) {
// Esperando la implementación de Object.defineProperty
}3. Usar Object.defineProperty
La propiedad de error debe declararse usando Object.defineProperty. En resumen, Object.defineProperty nos ayuda a definir y configurar propiedades en un objeto.
El método defineProperty recibe tres parámetros:
La instancia del objeto, el nombre de la propiedad y un objeto descriptor con el valor o con las funciones getter y setter.
Object.defineProperty(target, 'errors', {
value: `Your password should be bigger than ${limit}`
});4. Redefinir la propiedad usando Object.defineProperty y nuestras funciones
El siguiente paso es la clave: redefinir la propiedad con el decorador y configurar las funciones getter y setter para que trabajen con nuestra lógica.
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter
});¡Listo! Ahora que tenemos un panorama claro de cada parte, veamos el código completo.
function Min(limit: number) {
return function(target: Object, propertyKey: string) {
let value : string;
const getter = function() {
return value;
};
const setter = function(newVal: string) {
if(newVal.length < limit) {
Object.defineProperty(target, 'errors', {
value: `Your password should be bigger than ${limit}`
});
}
else {
value = newVal;
}
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter
});
}
}
El decorador ya está listo. Ahora, la clase User tendrá una propiedad password. Usando el decorador @Min, establezco que la longitud mínima de la contraseña sea 8:
class User {
username: string;
@Min(8)
password: string;
constructor(username: string, password: string){
this.username = username;
this.password = password;
}
}Al asignar la propiedad password en el constructor, se invocan nuestro decorador y las funciones internas de getter y setter.
let danyUser = new User("dany", "pass");
console.log(danyUser);
console.log(danyUser.errors);Como la contraseña no cumple con los requisitos, la propiedad errors estará disponible y contendrá el mensaje:
[nodemon] starting `node app.js`
User { username: 'dany' }
Your password should be bigger than 8Conclusión
Espero que este artículo te ayude a entender cómo y cuándo usar decoradores de propiedades en TypeScript. Si te gustó este post, ¡compártelo!
Foto de Ferenc Almasi en Unsplash
Modern frontend development — Angular, React, TypeScript, accessibility, and performance.
Artículos Relacionados
Compartir este artículo
Si esta guía te resultó útil, compártela con tu equipo o con otros desarrolladores.
Software real. Lecciones reales.
Comparto las lecciones que aprendí por las malas, para que puedas evitarlas o estar preparado cuando ocurran.
Únete a 13,800+ desarrolladores y lectores.
Cero spam. Cancela tu suscripción en cualquier momento.