Constantes en clases de TypeScript: de principiante a profesional
\n\n¿Alguna vez has escrito en TypeScript y de repente te has dado cuenta: «Esta cadena mágica "ADMIN" la uso en diez lugares, y si me equivoco al escribir, el compilador se calla»? Un dolor familiar. O, peor aún, alguien del equipo cambia el valor de una constante directamente en tiempo de ejecución, y pasas una hora depurando para entender por qué todo se rompió.
\n\nBienvenido al mundo de las constantes de clase en TypeScript. No es solo azúcar sintáctico, es la base de una arquitectura limpia, predecible y segura. En este artículo, analizaremos todas las formas de declarar constantes en clases de TypeScript: desde el simple readonly hasta técnicas avanzadas con as const y genéricos. ¡Allá vamos!
¿Por qué son importantes las constantes en las clases?
\n\nImagina que estás desarrollando una aplicación para una tienda en línea. Tienes una clase Order y dentro de ella hay estados: "pending", "shipped", "delivered". Si esparces estas cadenas por todo el código, tarde o temprano alguien escribirá "PENDING" en mayúsculas y el error está asegurado. Las constantes de clase en TypeScript resuelven este problema de una vez por todas.
- \n
- Seguridad de tipos: el compilador no permitirá pasar "pendingg" donde se necesita "pending". \n
- Legibilidad:
OrderStatus.Pendinges más claro que una simple cadena. \n - Mantenimiento: cambiar el valor en un lugar lo cambia en todas partes. \n
Método n.º 1: readonly — lo básico, pero con matices
\n\nLa forma más sencilla es usar el modificador readonly. Impide modificar el campo después de la inicialización.
class AppConfig {\n readonly API_URL: string = 'https://api.example.com';\n readonly MAX_RETRIES: number = 3;\n}\n\nconst config = new AppConfig();\nconsole.log(config.API_URL); // 'https://api.example.com'\n// config.API_URL = 'new-url'; // ¡Error! No se puede asignar a 'API_URL' porque es una propiedad de solo lectura.\n\nPero hay un truco: readonly solo funciona a nivel de TypeScript. En el JavaScript compilado, estos campos aún se pueden modificar. Para una protección completa, usa Object.freeze o # (campos privados).
Método n.º 2: static readonly — el rey de las constantes
\n\nSi la constante no está vinculada a una instancia específica de la clase (y esto ocurre en el 99% de los casos), usa static readonly. Este es el patrón clásico de class constant typescript.
class MathConstants {\n static readonly PI: number = 3.14159;\n static readonly E: number = 2.71828;\n static readonly GOLDEN_RATIO: number = 1.61803;\n}\n\n// Acceso sin crear una instancia\nconsole.log(MathConstants.PI); // 3.14159\n// MathConstants.PI = 3.14; // ¡Error!\n\nEste enfoque es ideal para configuraciones, constantes matemáticas, estados y cualquier valor que no deba cambiar.
\n\nMétodo n.º 3: enum — cuando hay muchas constantes
\n\nSi tienes un grupo de constantes relacionadas (por ejemplo, estados de un pedido), enum es tu mejor amigo. Crea un conjunto de valores con nombre.
enum OrderStatus {\n Pending = 'pending',\n Shipped = 'shipped',\n Delivered = 'delivered',\n Cancelled = 'cancelled'\n}\n\nclass Order {\n constructor(public status: OrderStatus) {}\n}\n\nconst order = new Order(OrderStatus.Pending);\nconsole.log(order.status); // 'pending'\n\n// order.status = 'pendingg'; // ¡Error! El tipo '"pendingg"' no se puede asignar al tipo 'OrderStatus'\n\nConsejo: si usas enum de cadenas (como en el ejemplo), proporcionan valores legibles en tiempo de ejecución. Los enum numéricos son más rápidos, pero más difíciles de depurar.
Método n.º 4: as const — para máxima rigurosidad
\n\nA veces quieres que un objeto o un array se vuelvan cons