Index Signature is een mechanisme voor het beschrijven van het type van objecten waarvan de sleutels van tevoren onbekend zijn (of dynamisch kunnen worden toegevoegd), terwijl de waarden overeenkomen met een bepaald type. Het maakt het mogelijk om woordenboekobjecten (map/dictionary) te maken, waarbij de lijst met eigenschappen niet bekend is op het moment van compilatie.
Achtergrond: in JavaScript fungeren objecten vaak als associatieve arrays. De statische typing van TypeScript vereist dat de types van de sleutels en waarden worden opgegeven. Index Signature lost het belangrijkste probleem op: het beschrijven van een object waarbij de sleutel geen hardcoded eigenschap is, maar een string (of getal), en de waarden van een bepaald type zijn.
Probleem: bij het werken met dergelijke objecten kan het voorkomen dat bekende eigenschappen van het object in conflict komen met de indexsignature, of dat informatie over specifieke eigenschappen verloren gaat. Er zijn nuances met geërfde types en het uitbreiden van de structuur van het woordenboek.
Oplossing: Index Signature wordt gebruikt om dynamische eigenschappen te beschrijven, meestal met een sleutel van het type string of number, bijvoorbeeld voor collecties, cache-objecten of API-responses van het type { [key: string]: T }. Om de controle over het type te behouden, is het noodzakelijk om zowel de vaste eigenschappen als de indexsignature samen te beschrijven, of, indien nodig, unie-types te maken.
Voorbeeldcode:
interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };
Belangrijke kenmerken:
Wat gebeurt er als je een vaste eigenschap met een incompatibel type toevoegt aan een interface met indexsignature?
TypeScript zal een foutmelding geven als het type van de eigenschap niet compatibel is met het type dat is opgegeven in de indexsignature.
interface BadDict { [key: string]: number; error: string; // Fout: string is niet compatibel met number }
Is het mogelijk om meerdere indexsignaturen met verschillende type sleutels (number en string) gelijktijdig te declareren?
Ja, dat kan, maar er is een nuance: in TypeScript worden sleutels van het type number automatisch omgezet naar een string. Een indexsignature met number is slechts een synoniem voor string-sleutels.
interface NumStrDict { [key: string]: number; [key: number]: number; }
Kun je unie-types of interfaces gebruiken voor de waarde in de indexsignature?
Ja, de waarde kan een unie-type of interface zijn. Op deze manier kunnen woordenboeken van complexe objecten worden beschreven.
interface Dict { [key: string]: string | number; }
In de interface van de API-respons werd [key: string]: any gebruikt. Later bevatte het geretourneerde object gegevens van verschillende structuren, wat leidde tot fouten tijdens runtime en het onderhoud van de code bemoeilijkte.
Voordelen:
Nadelen:
We hebben een interface voor een cache-object beschreven, waarbij de waarden van strikt bepaald type zijn (bijvoorbeeld UserData), met de opmerking dat de sleutel userId (string) is:
interface UserCache { [userId: string]: UserData; }
Voordelen:
Nadelen: