Los tipos enumerados en TypeScript son una herramienta muy útil que nos permite asignar automáticamente números secuenciales a sus valores, pero también nos ofrecen la flexibilidad de personalizar esos números o incluso usar cadenas de texto. Esto no solo mejora la claridad del código, sino que además mantiene un espacio de nombres propio para evitar conflictos y facilita la depuración y el uso en APIs.
Cuando declaramos un enum sin especificar valores, TypeScript asigna automáticamente números consecutivos empezando desde cero. Por ejemplo, si definimos un enum con los días de la semana, lunes tendrá el valor 0, martes el 1, y así sucesivamente. Este comportamiento no es exclusivo de TypeScript, sino que es común en muchos lenguajes como C. Lo importante aquí es que el orden en que declaramos los elementos determina el valor numérico que se les asigna, por lo que si cambiamos el orden, también cambiarán los valores.
Podemos modificar estos valores asignados manualmente. Por ejemplo, si queremos que lunes tenga el valor 401 porque la API con la que trabajamos usa números específicos, podemos asignarlo explícitamente. Al hacerlo, el contador interno se reinicia desde ese número, y los valores siguientes se asignan de forma secuencial a partir de ahí, a menos que también los definamos manualmente. Así, si jueves lo fijamos en 701, los valores quedarían como lunes = 401, martes = 402, miércoles = 403 y jueves = 701. Esto nos permite tener un control total sobre los valores numéricos, aunque debemos tener cuidado con la coherencia y evitar asignar valores duplicados, aunque técnicamente es posible.
Una ventaja importante de usar enums en lugar de constantes sueltas es que los enums crean su propio espacio de nombres. Esto significa que podemos tener dos enums diferentes con valores que se llamen igual, como lunes, sin que haya conflicto, algo que no podríamos hacer con constantes globales. Además, tener todos los valores agrupados en un enum mejora la legibilidad y la organización del código.
Sin embargo, a nivel interno, TypeScript asocia cada identificador con un número, y cuando accedemos a un valor del enum, lo que obtenemos es ese número. Por ejemplo, si hacemos console.log(diasemana.lunes), veremos el número 401 en lugar de la palabra lunes. Esto puede dificultar la depuración, ya que en la consola nos aparecerán números que pueden no ser intuitivos, especialmente si no conocemos la asignación exacta.
Para solucionar este problema, TypeScript permite definir enums con valores de tipo cadena. En lugar de asignar números, podemos asignar directamente cadenas de texto, como lunes = "lunes". Esto hace que cuando accedamos a diasemana.lunes, obtengamos la cadena "lunes", lo que facilita la lectura y depuración. Sin embargo, cuando usamos cadenas, TypeScript nos obliga a asignar explícitamente un valor a cada elemento del enum, ya que no puede inferir valores secuenciales como con números. Esto significa que si un elemento es una cadena, todos los siguientes deben tener valores constantes asignados.
Un detalle curioso es que esta restricción solo aplica a los elementos que vienen después de un valor de tipo cadena. Los elementos anteriores pueden ser números asignados automáticamente sin problema. Por ejemplo, si colocamos un elemento con valor cadena en medio del enum, los que estén después deben tener valores explícitos, pero los que estén antes pueden seguir con valores numéricos automáticos.
Finalmente, un aspecto avanzado de los enums en TypeScript es que podemos asignar valores computados. Esto significa que no estamos obligados a asignar solo valores constantes, sino que podemos usar expresiones que se calculan en tiempo de compilación o que dependen de otros valores del enum. Esto nos da mucha flexibilidad para definir enums que se ajusten a necesidades más complejas, aunque para ilustrar esto es mejor usar un ejemplo diferente a los días de la semana, ya que puede complicar la explicación.
En resumen, los enums en TypeScript nos ofrecen una forma poderosa y flexible de manejar conjuntos de valores relacionados, con opciones para valores automáticos, personalizados, de cadena y computados, lo que mejora la claridad, organización y mantenimiento de nuestro código.