TypeScript Map: een getypeerde key-value-collectie
TypeScript Map
TypeScript Map: typeren, doorlopen en opslaan | We.Inc
Typeer een Map<K, V> in TypeScript, loop erover, zet hem om naar JSON en terug, en kies tussen Map, Record en een gewoon object. Probeer een live Map in de browser.
In TypeScript is een Map de gewone JavaScript-Map met types voor zijn sleutels en waarden: new Map<string, number>(). Sleutels kunnen elke waarde zijn, entries komen terug in de volgorde waarin ze eerst zijn toegevoegd, size telt ze, en get geeft V | undefined terug. JSON.stringify serialiseert geen Map, dus zet hem eerst om.
Map-methoden en wat TypeScript teruggeeft
Aanroep
Doet
Type dat u krijgt (Map<string, number>)
map.set(k, v)
Voegt een entry toe of werkt hem bij
Map<string, number> (koppelbaar)
map.get(k)
Leest een waarde
number | undefined
map.has(k)
Controleert een sleutel
map.delete(k)
Verwijdert een entry
boolean (true als hij bestond)
Telt de entries
for (const [k, v] of map)
Loopt in volgorde van toevoegen
k: string, v: number
De playground hieronder is een echte Map die in uw browser draait. Voeg entries toe, werk ze bij en verwijder ze, en let op drie dingen: de volgorde die entries behouden, wat size meldt, en het verschil tussen het stringifyen van de Map zelf en van een omgezette kopie.
Typ een sleutel en een getal en druk op Instellen om die entry toe te voegen of bij te werken.
Druk op Verwijderen om de sleutel in het sleutelvak te verwijderen, of op Wissen om de Map te legen.
Lees de lijst met entries, die de eigen iteratievolgorde van de Map volgt.
Vergelijk de twee JSON-regels om te zien waarom een Map moet worden omgezet voordat u hem opslaat of verstuurt.
Geef de generieke argumenten mee als u een lege Map aanmaakt. new Map() op zichzelf is Map<any, any>, en elke latere leesactie verliest zijn type.
Controleer has() of vergelijk get() met undefined voordat u een waarde gebruikt. Een non-null assertion verbergt het geval waarin de sleutel echt ontbreekt.
Objectsleutels worden op referentie vergeleken. Twee objecten met dezelfde velden zijn twee verschillende sleutels, dus gebruik een id-string als u hetzelfde record bedoelt.
Om een Map in localStorage te bewaren, slaat u JSON.stringify([...map]) op en bouwt u hem opnieuw op met new Map(JSON.parse(text)). De array met paren behoudt sleutels die geen string zijn en de volgorde.
Veelgestelde vragen
Hoe declareer ik het type van een Map in TypeScript?
Geef de sleutel- en waardetypes mee als generieke argumenten: const prices = new Map<string, number>(). Schrijf voor een veld of parameter het type als Map<string, number>, of ReadonlyMap<string, number> als de functie hem alleen moet lezen.
Waarom bevat het type van map.get() undefined?
Omdat de compiler niet kan weten welke sleutels er op een bepaald moment in de Map zitten. get is getypeerd als V | undefined, dus u vernauwt met een if-controle, een ??-fallback of een has()-test voordat u de waarde als V behandelt.
Waarom geeft JSON.stringify(map) {}?
Een Map bewaart zijn entries in een interne slot, niet als objecteigenschappen, dus JSON ziet een leeg object. Zet hem eerst om: Object.fromEntries(map) voor string-sleutels, of [...map] voor een array met paren die elk sleuteltype overleeft.
Gebruik ik een Map of een Record?
Gebruik een Record voor een vaste set benoemde sleutels en voor data die van en naar JSON gaat. Gebruik een Map als entries komen en gaan terwijl de app draait, als sleutels getallen of objecten zijn, of als de volgorde van toevoegen ertoe doet.
Verplaatst het bijwerken van een sleutel die naar het einde?
Nee. Een bestaande sleutel opnieuw instellen wijzigt de waarde maar behoudt de oorspronkelijke positie. Om hem naar het einde te verplaatsen, verwijdert u de sleutel en stelt u hem opnieuw in.
Map, Record en een gewoon object
Een gewoon object erft van Object.prototype, dus namen zoals constructor zijn er al, en de sleutels zijn altijd strings of symbols. Een Map begint leeg, accepteert elke waarde als sleutel en meldt het aantal entries via size.
Record is een type, geen container. Het beschrijft een gewoon object, dus alles hierboven over objecten geldt er tijdens runtime ook voor, inclusief de ingebouwde JSON-ondersteuning die een Map mist.
Hoe sleutels worden vergeleken
Map vergelijkt sleutels met de SameValueZero-regel. Het getal 1 en de string "1" zijn verschillende sleutels, NaN komt overeen met NaN, en een object komt alleen met zichzelf overeen. Een gewoon object zou 1 omzetten in "1" en de twee samenvoegen.
Daardoor is een Map de natuurlijke cache voor waarden met een DOM-element, een functie of een request-object als sleutel, gevallen waarin een object een verzonnen string-id nodig zou hebben.
Maps typeren in functiesignaturen
Accepteer ReadonlyMap<K, V> in functies die alleen lezen. Dat haalt set, delete en clear uit het type, zodat de signatuur zelf aanroepers vertelt dat hun Map niet wordt gewijzigd.
Als u een Map bouwt uit een array met paren, leidt TypeScript de types af uit de paren. Voeg een expliciet generiek argument toe als de array leeg kan zijn of als de paren types mengen die u gescheiden wilt houden.
Recepten voor getypeerde Maps
Woorden tellen met een Map
De ??-fallback vangt de eerste keer dat een woord voorkomt af, en daarom is het juist handig en niet hinderlijk dat get number | undefined teruggeeft.
Een Map opslaan als JSON en weer inladen
Een array met paren behoudt elke entry en de volgorde ervan. Object.fromEntries is de leesbare keuze als elke sleutel een string is.
Een alleen-lezen Map accepteren
Binnen total zou prices.set aanroepen een compileerfout zijn, dus aanroepers kunnen hun Map doorgeven zonder defensieve kopie.
Live Map-playground
Sleutel
Waarde (getal)
Instellen
Verwijderen
Wissen
Herstellen
Entries in iteratievolgorde
De Map is leeg.
size: {n}
"{v}" toegevoegd.
"{v}" verwijderd.
"{v}" staat niet in de Map, dus delete gaf false terug.