L'Index Signature è un meccanismo per descrivere il tipo di oggetti i cui chiavi sono sconosciute in anticipo (o possono essere aggiunte dinamicamente), e i cui valori corrispondono a un tipo specifico. Permette di creare oggetti-dizionario (map/dictionary), dove l'elenco delle proprietà è sconosciuto al momento della compilazione.
Storia della questione: in JavaScript, gli oggetti spesso fungono da array associativi. La tipizzazione statica di TypeScript richiede di specificare i tipi delle chiavi e dei valori. L'Index Signature risolve il problema principale: descrivere un oggetto in cui la chiave non è una proprietà rigidamente definita, ma una stringa (o un numero), e i valori sono di un tipo specifico.
Problema: quando si lavora con tali oggetti, è possibile incorrere in situazioni in cui le proprietà note dell'oggetto confliggono con l'index signature, o si perde informazione sulle proprietà specifiche. Ci sono sfide con i tipi ereditati e l'estensione della struttura del dizionario.
Soluzione: l'Index Signature viene utilizzata per descrivere proprietà dinamiche, di solito con chiave di tipo string o number, per esempio per collezioni, oggetti di cache o risposte API del tipo { [key: string]: T }. Per mantenere il controllo sul tipo, è necessario descrivere sia le proprietà fisse sia l'index signature insieme, oppure, se necessario, comporre tipi union.
Esempio di codice:
interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };
Caratteristiche chiave:
Cosa succede se aggiungi una proprietà fissa con un tipo non compatibile a un'interfaccia con index signature?
TypeScript genererà un errore se il tipo della proprietà non è compatibile con il tipo specificato nell'index signature.
interface BadDict { [key: string]: number; error: string; // Errore: string non compatibile con number }
È possibile dichiarare più index signature con tipi di chiavi diversi (number e string) contemporaneamente?
Sì, è possibile, ma c'è una sfumatura: in TypeScript, le chiavi di tipo number vengono automaticamente convertite in string. L'index signature con number è quindi solo un sinonimo per le chiavi string.
interface NumStrDict { [key: string]: number; [key: number]: number; }
Posso usare tipi union o interfacce per il valore nell'index signature?
Sì, il valore può essere di tipo union o un'interfaccia. In questo modo, puoi descrivere dizionari di oggetti complessi.
interface Dict { [key: string]: string | number; }
Nell'interfaccia della risposta API abbiamo usato [key: string]: any. Successivamente, l'oggetto restituito conteneva dati di diverse strutture, portando a errori di runtime e complicando la manutenzione del codice.
Pro:
Contro:
Abbiamo descritto l'interfaccia di un oggetto di cache, dove i valori sono di tipo rigorosamente definito (ad esempio, UserData), con un commento che spiega che la chiave è userId (string):
interface UserCache { [userId: string]: UserData; }
Pro:
Contro: