Cuando queremos implementar un sistema de permisos, como el que podríamos encontrar en una red social o en plataformas como Discord, es común pensar en usar enumerados para representar cada permiso disponible. Por ejemplo, podríamos tener permisos para escribir mensajes, reaccionar, enviar enlaces o conectarse a canales de voz. En TypeScript, si no especificamos valores, los enumerados asignan automáticamente números secuenciales empezando desde cero. Sin embargo, en el contexto de permisos, asignar el valor cero a un permiso no tiene mucho sentido, porque cero suele representar la ausencia de permisos.
Para manejar esto de forma eficiente, podemos asignar valores que representen bits individuales, como 1, 2, 4, 8, y así sucesivamente. De esta manera, cada permiso corresponde a un bit distinto en un número, y podemos combinar permisos sumando esos valores. Por ejemplo, si un usuario tiene permisos con valor 6, eso significa que tiene los permisos correspondientes a 2 y 4, es decir, puede reaccionar y enviar enlaces. Este sistema de máscaras de bits es muy potente y eficiente, y es común en la gestión interna de permisos en sistemas informáticos.
Pero asignar manualmente estos valores puede ser tedioso y propenso a errores. Aquí es donde entran en juego los enumerados con valores computados en TypeScript. En lugar de escribir explícitamente cada valor, podemos definir que cada permiso sea el doble del anterior, usando expresiones que multipliquen por 2 el valor del permiso previo. Por ejemplo, podemos definir que el permiso de reaccionar sea el doble del permiso de escribir mensajes, el permiso de enviar enlaces sea el doble del permiso de reaccionar, y así sucesivamente.
Esto se traduce en un código como el siguiente:
enum Permisos {
EscribirMensajes = 1,
Reaccionar = EscribirMensajes * 2,
EnviarEnlaces = Reaccionar * 2,
ConectarseCanalesVoz = EnviarEnlaces * 2,
}
Gracias a esta técnica, TypeScript calcula automáticamente los valores numéricos correspondientes a cada permiso, que serían 1, 2, 4 y 8 respectivamente. Esto facilita la gestión y evita errores al asignar manualmente los valores.
Además, podemos usar constantes para inicializar estos valores, lo que nos da flexibilidad para cambiar el punto de partida sin modificar todo el enumerado. Por ejemplo, si definimos una constante inicial con valor 8, podemos usarla para que el primer permiso tenga ese valor y los siguientes se multipliquen por 2 sucesivamente:
const inicial = 8;
enum Permisos {
EscribirMensajes = inicial,
Reaccionar = EscribirMensajes * 2,
EnviarEnlaces = Reaccionar * 2,
ConectarseCanalesVoz = EnviarEnlaces * 2,
}
Esto hace que los valores sean 8, 16, 32 y 64 respectivamente.
Incluso es posible usar funciones para calcular los valores, aunque hay que tener cuidado con esto. Por ejemplo, asignar un valor aleatorio a un permiso es legal en TypeScript, pero puede no tener sentido práctico, ya que los permisos deberían ser constantes y predecibles para que el sistema funcione correctamente.
El objetivo principal de usar enumerados con valores computados es facilitar la programación, haciendo que sea sencillo reconocer y manejar cada permiso, mientras que internamente se usan valores numéricos que permiten operaciones eficientes, como combinar permisos mediante operaciones bit a bit.
Sin embargo, no siempre es necesario usar enumerados. En muchos casos, especialmente en librerías como Redux en React, donde se necesitan identificadores únicos para acciones, puede ser tentador usar enumerados, pero no siempre es la mejor solución. Los enumerados son útiles en situaciones concretas, pero no debemos abusar de ellos ni complicar demasiado nuestro código cuando existen alternativas más sencillas.
Por eso, es importante tener en cuenta cuándo realmente necesitamos enumerados y cuándo podemos optar por soluciones más simples. Así, mantenemos nuestro código claro y eficiente, usando enumerados con valores computados solo cuando aportan un beneficio real en la gestión de permisos o en otros casos similares.