Map di TypeScript adalah Map bawaan JavaScript dengan key dan value yang bertipe: Map<string, number> memetakan string ke angka. Buat dengan new Map<K, V>(), lalu pakai set, get, has, dan delete. get mengembalikan V | undefined, karena key-nya bisa saja tidak ada.
Argumen tipe itulah yang membuat Map berguna di TypeScript: setiap set diperiksa, dan setiap get mengembalikan tipe value. Baris terakhir adalah error kompilasi (TS2345); @ts-expect-error membuat blok ini tetap bisa dijalankan.
Halaman ini membahas koleksi Map. Kalau kamu sedang mencari array.map(), materinya ada di bagian terakhir.
Membuat Map
Tipenya berasal dari argumen tipe, dari entri awal, atau dari anotasi. Entri awal berupa array berisi tuple [key, value], atau apa pun yang menghasilkan tuple seperti itu.
Ada dua jebakan inferensi:
new Map()tanpa argumen tipe dan tanpa entri bertipeMap<any, any>. Apa pun yang kamu masukkan atau ambil tidak diperiksa. Selalu tulisnew Map<K, V>().- Entri dengan tipe value yang berbeda tidak disimpulkan menjadi union.
new Map([["a", 1], ["b", "x"]])adalah error TS2769 (No overload matches this call). Tulis tipenya:new Map<string, number | string>([...]).
get Mengembalikan V | undefined
Map tidak bisa menjanjikan bahwa sebuah key ada, jadi get bertipe V | undefined. Dengan strict, kamu harus menangani undefined sebelum memakai nilainya sebagai V:
index.ts(4,7): error TS2322: Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.
Cara memperbaikinya, dari yang paling umum sampai yang paling jarang:
TypeScript tidak ingat bahwa has mengembalikan true saat kamu memanggil get sesudahnya. Memeriksa hasil get secara langsung lebih ringkas sekaligus aman. Non-null assertion, stock.get("apples")!, memang menghilangkan error-nya, tetapi tidak memberi perlindungan apa pun kalau key-nya tidak ada.
Method Map dan Tipenya
| Member | Tipe pada Map<K, V> | Catatan |
|---|---|---|
new Map<K, V>(entries?) | Map<K, V> | entries: iterable berisi [K, V] |
set(key, value) | this | Menambah atau mengganti; bisa dirangkai |
get(key) | V | undefined | undefined kalau tidak ada |
has(key) | boolean | |
delete(key) | boolean | true kalau ada yang dihapus |
clear() | void | Menghapus semuanya |
size | number | Properti, bukan method |
keys(), values() | iterator berisi K, V | Spread ke dalam array: [...map.keys()] |
entries(), for...of | iterator berisi [K, V] | Sesuai urutan penyisipan |
forEach((value, key) => ...) | void | Perhatikan: value ada di urutan pertama |
Iterasi Map
Map diiterasi sesuai urutan penyisipan. for...of pada map menghasilkan tuple [key, value], bertipe [K, V].
Mengatur key yang sudah ada akan memperbarui value-nya tetapi mempertahankan posisi awalnya dalam urutan.
Key Berupa Object dan Menghitung
Nilai apa pun bisa menjadi key, termasuk object dan array. Key dibandingkan seperti ===: dua object dengan isi yang sama adalah key yang berbeda. Map juga merupakan cara standar untuk menghitung atau mengelompokkan item.
Untuk membuat key berdasarkan isi object, turunkan key berupa string atau angka, seperti user.id atau `${x},${y}`.
Map vs Object vs Record
Map<K, V> | Object / Record<string, V> | |
|---|---|---|
| Tipe key | apa saja, dibandingkan seperti === | string (angka menjadi string), symbol |
| Tipe untuk key yang tidak ada | get mengembalikan V | undefined | obj[key] bertipe V kecuali noUncheckedIndexedAccess aktif |
| Urutan | urutan penyisipan | sebagian besar urutan penyisipan, tetapi key yang mirip bilangan bulat didahulukan dengan urutan naik |
| Ukuran | map.size | Object.keys(obj).length |
| Sering menambah dan menghapus | dioptimalkan untuk itu | tidak dioptimalkan untuk itu |
| JSON | tidak langsung (JSON.stringify(map) menghasilkan "{}") | langsung |
| Sintaks literal, destructuring | tidak | ya |
| Key warisan yang tidak disengaja | tidak ada | "toString" in {} bernilai true |
Aturan praktisnya: Map untuk koleksi yang key-nya adalah data (id user, kata, entri cache) dan berubah saat runtime; tipe object atau Record untuk sekumpulan key tetap yang sudah diketahui, dan untuk apa pun yang dikirim ke atau diterima dari JSON. Halaman dictionary membandingkan index signature, Record, dan Map untuk lookup dengan key berupa string.
Mengubah Map menjadi Object dan JSON
Entri Map bukan properti, jadi JSON.stringify tidak melihatnya. Konversi lewat Object.fromEntries dan Object.entries:
JSON.parse mengembalikan any, jadi as Record<...> menyatakan bentuk data yang diharapkan. Itu bukan pemeriksaan saat runtime; validasi JSON yang tidak tepercaya sebelum memercayai tipe tersebut.
Memberi Tipe pada array.map()
Banyak pencarian "typescript map" sebenarnya mencari method array, yang mengubah setiap elemen dan mengembalikan array baru. Tipenya disimpulkan dari callback, jadi anotasi jarang dibutuhkan:
Memberi anotasi pada tipe kembalian callback ((u): Option => ...) adalah cara paling jelas untuk menyatakan tipe hasilnya: properti yang hilang atau salah ketik di object yang dikembalikan lalu menjadi error kompilasi di callback tersebut.
Pertanyaan yang sering diajukan
Bagaimana cara membuat Map di TypeScript?
Kirim tipe key dan value ke constructor: const ages = new Map<string, number>(). Dengan entri awal, tipenya disimpulkan: new Map([["ada", 36]]) adalah Map<string, number>. new Map() polos tanpa tipe dan tanpa entri bertipe Map<any, any>, yang mematikan pemeriksaan, jadi selalu beri tipe.
Kenapa Map.get bisa mengembalikan undefined di TypeScript?
map.get(key) bertipe V | undefined karena key-nya mungkin tidak ada. TypeScript tidak menghubungkan map.has(key) sebelumnya dengan get sesudahnya, jadi bahkan setelah has kamu tetap perlu menangani undefined: simpan hasilnya lalu periksa, atau pakai nilai default dengan ??.
Apa perbedaan Map dan object di TypeScript?
Map menerima key bertipe apa pun (termasuk object), mempertahankan urutan penyisipan, punya size, dan dirancang untuk sering menambah dan menghapus. Object biasa atau Record<string, V> hanya punya key berupa string (dan symbol), bisa langsung diserialisasi ke JSON, serta mendukung sintaks literal dan destructuring. Pakai Map untuk koleksi ber-key yang dinamis, dan object untuk bentuk yang tetap serta data JSON.
Bagaimana cara mengubah Map menjadi object atau JSON di TypeScript?
Object.fromEntries(map) mengubah Map<string, V> menjadi object biasa, yang lalu bisa diserialisasi oleh JSON.stringify. JSON.stringify(map) langsung pada Map menghasilkan "{}", karena entri Map bukan properti. Kebalikannya adalah new Map(Object.entries(obj)).
Bagaimana cara memberi tipe pada callback array.map di TypeScript?
Biasanya tidak perlu: items.map((item) => item.name) menyimpulkan item dari array dan tipe hasilnya dari apa yang dikembalikan callback. Untuk memaksakan tipe hasil, kirim sebagai argumen tipe, items.map<string>(...), atau beri anotasi pada tipe kembalian callback-nya.