Index Signature es un mecanismo para describir el tipo de objetos cuyas claves son desconocidas por adelantado (o pueden ser agregadas dinámicamente), y cuyos valores corresponden a un tipo determinado. Permite crear objetos de diccionario (map/dictionary), donde la lista de propiedades es desconocida en el momento de la compilación.
Historia del tema: en JavaScript, los objetos a menudo funcionan como arreglos asociativos. La tipificación estática de TypeScript requiere especificar los tipos de claves y valores. Index Signature resuelve el problema principal: describir un objeto donde la clave no es una propiedad fija, sino una cadena (o un número), y los valores son de un tipo determinado.
Problema: al trabajar con estos objetos, se puede caer en la situación donde las propiedades conocidas del objeto entran en conflicto con la index signature, o se pierde información sobre propiedades específicas. Hay matices con tipos heredados y la extensión de la estructura del diccionario.
Solución: Index Signature se utiliza para describir propiedades dinámicas, generalmente con una clave de tipo string o number, por ejemplo, para colecciones, objetos de caché o respuestas de API del tipo { [key: string]: T }. Para mantener el control sobre el tipo, es necesario describir tanto las propiedades fijas como la index signature juntas, o, si es necesario, formar tipos union.
Ejemplo de código:
interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };
Características clave:
¿Qué sucede si se agrega una propiedad fija con un tipo incompatible en una interfaz con index signature?
TypeScript generará un error si el tipo de la propiedad no es compatible con el tipo especificado en la index signature.
interface BadDict { [key: string]: number; error: string; // Error: string no es compatible con number }
¿Se pueden declarar múltiples index signatures con diferentes tipos de claves (number y string) al mismo tiempo?
Sí, se puede, pero hay un matiz: en TypeScript, las claves de tipo number se convierten automáticamente en cadenas. La index signature con number es simplemente un sinónimo para las claves de tipo string.
interface NumStrDict { [key: string]: number; [key: number]: number; }
¿Se pueden usar tipos union o interfaces para el valor en index signature?
Sí, el valor puede ser un tipo union o una interfaz. De esta manera, se pueden describir diccionarios de objetos complejos.
interface Dict { [key: string]: string | number; }
En la interfaz de respuesta de la API se utilizó [key: string]: any. Más tarde, el objeto devuelto contenía datos de diferentes estructuras, lo que llevó a errores en tiempo de ejecución y dificultó el mantenimiento del código.
Ventajas:
Desventajas:
Describimos una interfaz para un objeto de caché, donde los valores son de un tipo estrictamente definido (por ejemplo, UserData), con el comentario que la clave es userId (string):
interface UserCache { [userId: string]: UserData; }
Ventajas:
Desventajas: