Map w TypeScript: otypowana kolekcja klucz-wartość
Map w TypeScript
Map w TypeScript: typowanie, iteracja i zapisywanie | We.Inc
Otypuj Map<K, V> w TypeScript, iteruj po nim, zamień go na JSON i z powrotem oraz zdecyduj między Map, Record a zwykłym obiektem. Wypróbuj działający Map w przeglądarce.
W TypeScript Map to zwykły Map z JavaScriptu z typami dla kluczy i wartości: new Map<string, number>(). Kluczem może być dowolna wartość, wpisy wracają w kolejności, w jakiej zostały pierwotnie dodane, size je liczy, a get zwraca V | undefined. JSON.stringify nie serializuje Map, więc najpierw go przekonwertuj.
Metody Map i co zwraca TypeScript
Wywołanie
Działanie
Typ, który dostajesz (Map<string, number>)
map.set(k, v)
Dodaje lub aktualizuje wpis
Map<string, number> (można łączyć w łańcuch)
map.get(k)
Odczytuje wartość
number | undefined
map.has(k)
Sprawdza klucz
map.delete(k)
Usuwa wpis
boolean (true, jeśli istniał)
Liczy wpisy
for (const [k, v] of map)
Iteruje w kolejności dodania
k: string, v: number
Poniższy playground to prawdziwy Map działający w Twojej przeglądarce. Dodawaj, aktualizuj i usuwaj wpisy i obserwuj trzy rzeczy: kolejność, jaką zachowują wpisy, co zwraca size, oraz różnicę między zamianą na tekst samego Map a skonwertowanej kopii.
Wpisz klucz i liczbę, a potem naciśnij Ustaw, aby dodać lub zaktualizować ten wpis.
Naciśnij Usuń, aby usunąć klucz z pola klucza, albo Wyczyść, aby opróżnić Map.
Przeczytaj listę wpisów, która odpowiada własnej kolejności iteracji Map.
Porównaj dwie linie JSON, aby zobaczyć, dlaczego Map trzeba przekonwertować przed zapisaniem lub wysłaniem.
Podawaj argumenty generyczne przy tworzeniu pustego Map. Samo new Map() to Map<any, any>, a każdy późniejszy odczyt traci typ.
Przed użyciem wartości sprawdź has() lub porównaj wynik get() z undefined. Asercja non-null ukrywa przypadek, w którym klucza naprawdę brakuje.
Klucze obiektowe są porównywane przez referencję. Dwa obiekty z tymi samymi polami to dwa różne klucze, więc używaj stringu id, gdy chodzi Ci o ten sam rekord.
Aby trzymać Map w localStorage, zapisz JSON.stringify([...map]) i odtwórz go przez new Map(JSON.parse(text)). Tablica par zachowuje klucze niebędące stringami i kolejność.
Najczęściej zadawane pytania
Jak zadeklarować typ Map w TypeScript?
Przekaż typy klucza i wartości jako argumenty generyczne: const prices = new Map<string, number>(). Dla pola lub parametru zapisz typ jako Map<string, number> albo ReadonlyMap<string, number>, gdy funkcja ma go tylko czytać.
Dlaczego map.get() ma w typie undefined?
Ponieważ kompilator nie może wiedzieć, jakie klucze są w Map w danym momencie. get ma typ V | undefined, więc zawężasz go sprawdzeniem if, wartością zastępczą ?? lub testem has(), zanim potraktujesz wartość jako V.
Dlaczego JSON.stringify(map) daje {}?
Map przechowuje wpisy w wewnętrznym slocie, a nie jako właściwości obiektu, więc JSON widzi pusty obiekt. Najpierw przekonwertuj: Object.fromEntries(map) dla kluczy tekstowych albo [...map] dla tablicy par, która działa z każdym typem klucza.
Używać Map czy Record?
Używaj Record dla stałego zestawu nazwanych kluczy i danych, które trafiają do JSON i z niego wracają. Używaj Map, gdy wpisy pojawiają się i znikają podczas działania aplikacji, gdy klucze są liczbami lub obiektami albo gdy liczy się kolejność dodania.
Czy aktualizacja klucza przenosi go na koniec?
Nie. Ustawienie istniejącego klucza zmienia jego wartość, ale zachowuje pierwotną pozycję. Aby przenieść go na koniec, usuń klucz i ustaw go ponownie.
Map, Record i zwykły obiekt
Zwykły obiekt dziedziczy po Object.prototype, więc nazwy takie jak constructor już w nim są, a jego klucze to zawsze stringi lub symbole. Map zaczyna jako pusty, przyjmuje dowolną wartość jako klucz i podaje liczbę wpisów przez size.
Record to typ, a nie kontener. Opisuje zwykły obiekt, więc wszystko, co powyżej powiedziano o obiektach, dotyczy go w czasie działania, w tym natywna obsługa JSON, której Map nie ma.
Jak dopasowywane są klucze
Map porównuje klucze według reguły SameValueZero. Liczba 1 i string "1" to różne klucze, NaN pasuje do NaN, a obiekt pasuje tylko do samego siebie. Zwykły obiekt zamieniłby 1 na "1" i scalił oba klucze.
Dlatego Map jest naturalnym cache dla wartości kluczowanych elementem DOM, funkcją lub obiektem żądania, czyli w przypadkach, w których obiekt wymagałby wymyślonego tekstowego id.
Typowanie Map w sygnaturach funkcji
W funkcjach, które tylko czytają, przyjmuj ReadonlyMap<K, V>. Usuwa to set, delete i clear z typu, więc sama sygnatura mówi wywołującym, że ich Map nie zostanie zmieniony.
Gdy budujesz Map z tablicy par, TypeScript inferuje typy z par. Dodaj jawny typ generyczny, gdy tablica może być pusta albo gdy pary mieszają typy, które chcesz trzymać osobno.
Przepisy na otypowany Map
Licz słowa za pomocą Map
Wartość zastępcza ?? obsługuje pierwsze wystąpienie słowa, dlatego to, że get zwraca number | undefined, pomaga, a nie przeszkadza.
Zapisz Map jako JSON i wczytaj z powrotem
Tablica par zachowuje każdy wpis i jego kolejność. Object.fromEntries to czytelny wybór, gdy każdy klucz jest stringiem.
Przyjmuj Map tylko do odczytu
Wewnątrz total wywołanie prices.set byłoby błędem kompilacji, więc wywołujący mogą przekazać swój Map bez kopii obronnej.