Diccionarios en TypeScript: del caos al orden (guía completa con código)
\n\nImagine que está escribiendo una aplicación para aprender inglés. Necesita almacenar traducciones de palabras: "cat" → "gato", "dog" → "perro". ¿Cuál es la mejor manera de organizar estos datos? Por supuesto, usar un diccionario (Dictionary) — una estructura de datos donde cada clave es única y está asociada a un valor.
En JavaScript, los diccionarios se implementan mediante objetos comunes o Map. Pero TypeScript añade una potente tipificación, transformando colecciones caóticas en estructuras estrictas y predecibles. En este artículo, analizaremos la declaración e inicialización de Dictionary en TypeScript de lo simple a lo complejo. Aprenderá a evitar errores típicos y a escribir código que funcione de manera predecible.
¿Qué es un Dictionary en TypeScript? (Y por qué no es solo un objeto)
\n\nEn programación, un Dictionary (diccionario) es una colección de pares «clave-valor». En TypeScript, puede crearlo de tres maneras principales:
\n\n- \n
- Objeto con firma de índice (
{ [key: string]: T }) \n - Record — tipo utilitario \n
- Map — clase incorporada de ES6 \n
Cada enfoque tiene sus ventajas y matices. Analicémoslos con ejemplos reales.
\n\nMétodo 1: Objeto clásico con firma de índice
\n\nLa forma más popular de declarar un diccionario en TypeScript es usar una firma de índice. Esto le dice al compilador: «El objeto puede tener cualquier cantidad de propiedades con claves de un tipo específico».
\n\n// Declaramos el tipo de diccionario, donde la clave es string, el valor es number\ninterface DictionaryNumber {\n [key: string]: number;\n}\n\n// Inicialización\nconst ages: DictionaryNumber = {\n "Ana": 25,\n "Pedro": 30,\n "Elena": 28\n};\n\n// Agregar un nuevo elemento\nages["Olga"] = 35;\n\nconsole.log(ages["Ana"]); // 25\n\nImportante: TypeScript requiere que todos los valores coincidan con el tipo declarado. Intentar agregar una cadena causará un error de compilación:
\n\n// ¡Error! El tipo 'string' no se puede asignar al tipo 'number'\nages["Olga"] = "treinta y cinco";\n\n¿Cuándo usar este enfoque?
\n- \n
- Cuando se necesita un diccionario simple y rápido \n
- Cuando las claves son cadenas o números \n
- Para colecciones pequeñas (hasta 1000 elementos) \n
Método 2: Record — sintaxis elegante
\n\nTypeScript proporciona el tipo utilitario incorporado Record<K, V>. Crea un tipo de objeto donde todas las claves son del tipo K y los valores del tipo V.
// Declaración e inicialización en una línea\nconst grades: Record<string, number> = {\n "Matemáticas": 5,\n "Física": 4,\n "Historia": 5\n};\n\n// Se puede usar un enum para las claves\nenum Subject {\n Math = "math",\n Physics = "physics",\n History = "history"\n}\n\nconst gradesBySubject: Record<Subject, number> = {\n [Subject.Math]: 5,\n [Subject.Physics]: 4,\n [Subject.History]: 5\n};\n\nVentajas de Record:
\n- \n
- Sintaxis concisa \n
- Buena legibilidad \n
- Soporte para tipos unión en las claves \n
Método 3: Map — para escenarios avanzados
\n\nLa clase Map de ES6 es una colección completa de «clave-valor» con capacidades adicionales. En TypeScript, se tipifica mediante genéricos:
// Declaración de Map\nconst userRoles: Map<string, string> = new Map([\n ["admin", "Administrador"],\n ["user", "Usuario"],\n ["guest", "Invitado"]\n]);\n\n// Agregar\nuserRoles.set("moderator", "Moderador");\n\n// Obtener\nconsole.log(userRoles.get("admin")); // "Administrador"\n\n// Verificar existencia\nif (userRoles.has("user")) {\n console.log("El rol existe");\n}\n\n// Y