A React no le gustan los decoradores
¿Estás usando React junto con Typescript y tienes problemas para trabajar con los decoradores que nos ofrece este popular lenguaje? Aquí la solución.
Índice de contenidos
Introducción
A estas alturas del partido no es necesario explicar qué es React. Pero si eres nuevo desarrollando he aquí unos datos:
React es una herramienta Javascript que nos permite crear interfaces de usuario.
Se define en ocasiones como framework o librería. Es parte del big three de los frameworks más actuales junto con Vue y Angular, su uso va en aumento y parece ser que este 2021 seguirá la tendencia al alza.
No vamos a hablar sobre todas las ventajas, que son muchas, que tiene esta popular herramienta ni tampoco sobre las desventajas de su uso, que también las hay.
Nos vamos a centrar en el uso de los decoradores Typescript en algunas piezas de nuestro proyecto.
Los decoradores en el mundo Typescript es azúcar sintáctico. En tiempo de compilación desaparecen y como pequeño apunte para entenderlos, se podría decir que son anotaciones las cuales colocamos en la parte superior de una clase, o alguno de sus miembros, cambiando el comportamiento de esta. Los decoradores existen en muchos lenguajes pero nosotros nos centraremos en Typescript y su uso en una aplicación realizada con React.
A React no le gustan los decoradores, dicho queda. Dan Abramov, creador de la herramienta viene a decir que los decoradores aún están muy verdes y su especificación sigue cambiando constantemente y podría poner en peligro el ecosistema de React.
Esto no quiere decir que no se puedan usar. A continuación te expongo el siguiente caso.
Problema
Tenemos una aplicación desarrollada con React y Typescript donde queremos usar la librería Tsyringe que es gran elección para la inyección de dependencias, la instalamos y configuramos como nos indica la documentación de dicho paquete.
Colocamos el decorador @injectable() en la parte superior de la clase correspondiente. Entre otras funciones, este decorador es un mecanismo que se encarga de extraer la responsabilidad de creación de instancias de un componente. Cuando creemos que nada puede ir mal, ¡error!, nuestra app nos muestra el siguiente mensaje nada halagüeño.
<<Error: TypeInfo not known for "nombre-clase">>
¿Qué ha pasado? Si todo iba bien, el éxito llamaba a nuestra puerta y ya estabamos pensando en el próximo tuit alardeando de lo bueno que somos. Recuerda esto: no eres un buen programador si no alardeas de ello en Twitter.
No pasa nada, no hay drama, el problema se encuentra en la herramienta Babel y la configuración que React le da por defecto. Cuando Babel pasa el rodillo (transpila) elimina los decoradores porque no los reconoce como algo válido, piensa que eliminándolos optimizará nuestro código. Bien por Babel, pero sin él saberlo nos ha dejado sin la preciada funcionalidad que nos da dicho decorador.
Solución
Para solucionarlo debemos abrir las entrañas React y tocar la configuración de Babel. No suena bien, ¿verdad?. Por suerte existen paquetes que nos hacen el trabajo sucio y con solo instalarlas y añadir unas lineas de configuración, todo funcionará como es debido.
Asumimos que usas npm o yarn como gestor de paquetes o alguno del estilo, si no es así, no nos explicamos cómo has llegado hasta este punto. Instalaremos la librería Craco, que será la encargada de abrirnos una pequeña puerta al interior del framework y poder cambiar la configuracion de Babel o Webpack. Teclea en tu terminal:
npm install -D @craco/craco
Si todo ha ido bien, creamos en la raíz de nuestro proyecto el siguiente archivo de configuración craco.config.js, y en su interior indicamos:
module.exports = {
babel: {
plugins: [
'babel-plugin-transform-typescript-metadata',
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }]
],
presets: ['@babel/preset-typescript']
}
}
El siguiente paso será modificar nuestro package.json:
"script: {
"start": "craco start",
"build": "craco build",
"test": "craco test",
...
}
Por último, ya solo te queda instalar uno de los muchos plugins de los que dispone Babel y que en el paso anterior ya indicamos en la configuración de Craco.
npm install -D babel-plugin-transform-typescript-metadata
Con estos cambios todo irá como la seda. React y Babel convivirán con los decoradores y tú te sentirás un desarrollador frontend más completo.
Listo, ves que no fue para tanto, ¡a programar!.
Bonus
Si te encuentras con el siguiente error:
Experimental support for decorators is a feature that is
subject to change in a future release. Set the
'experimentalDecorators' option in your 'tsconfig' or
'jsconfig' to remove this warning.
tsconfig.json tiene la solución. Entre sus propiedades añade lo siguiente:
"compilerOptions": {
...
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}