ProgrammatieFullstack ontwikkelaar

Hoe werkt het mechanisme van dynamische indexsignatuur (Index Signature) in TypeScript? Waarvoor wordt het gebruikt en wat zijn de belangrijkste valkuilen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

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:

  • Maakt het mogelijk om objecten met een dynamische set eigenschappen te beschrijven
  • De sleutel kan string, number of symbol zijn
  • Indexsignature beïnvloedt de typing van alle eigenschappen van het object

Vragen met een val

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; }

Typische fouten en anti-patterns

  • Incompatibiliteit van de type van vaste eigenschappen en de indexsignature
  • Gebruik van elk type waarde (bijvoorbeeld [key: string]: any)
  • Hiaten in de documentatie, onduidelijk wat een sleutel kan zijn

Voorbeeld uit het leven

Negatief geval

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:

  • Snelle beschrijving van een willekeurige structuur
  • Eenvoudig in gebruik

Nadelen:

  • Gemakkelijk om een typefout te maken
  • Onduidelijke structuur van objecten

Positief geval

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:

  • Duidelijke typing
  • Eenvoudig te gebruiken en uit te breiden

Nadelen:

  • Verhindert niet verkeerd gebruik van sleutels
  • Kan moeilijk te combineren zijn met vaste eigenschappen