TypeScript Tutorial
TypeScript Map
Map stores key-value pairs. Lookup by key instead of scanning a list.
Lookup by key
An array answers “what is at index 2?” A Map answers “what value sits under this key?” The key might be a part name, a user id, or a word. You do not walk the whole list to find it.
The type is Map<Key, Value>. This chapter uses Map<string, number>: a string key and a number value. Construct with new Map<string, number>(). C++map<string, int> is the same idea; TypeScript’s Map keeps insertion order, not sorted order.
set and get
stock.set("nails", 40) creates the key if it is new, or replaces the value if it already exists.stock.get("nails") returns that number, or undefined if the key is missing. Always account for that missing case under strict null checks.
Example
const stock = new Map<string, number>();
stock.set("nails", 40);
stock.set("screws", 12);
console.log(stock.get("nails"));
console.log(stock.get("screws"));Output is 40 then 12.
Use Try it in TypeScript so the program opens at /typescript/try. tsc compiles it in the browser. The C++ page at /cpp/try will not accept this code.
has before you treat a key as present
get returns number | undefined. has(key) is the yes-or-no test. Afterhas is true you can still use ?? when you print, because tsc does not always narrowget from a separate has call.
Example
const stock = new Map<string, number>();
stock.set("bolts", 8);
stock.set("bolts", 99);
console.log(stock.get("bolts"));
console.log(stock.has("bolts"));
console.log(stock.has("glue"));
console.log(stock.get("glue") ?? "missing");Output is 99, then true, then false, then missing. The secondset replaced 8 with 99. There is still no "glue" key.
Iterate in insertion order
A for...of on a map visits each pair. Destructure as [key, value]. Unlike C++std::map, JavaScript’s Map does not sort keys. The loop is the order you first inserted each key.
Example
const stock = new Map<string, number>();
stock.set("screws", 12);
stock.set("nails", 40);
stock.set("bolts", 8);
for (const [key, value] of stock) {
console.log(key + " " + value);
}The three lines print as screws, nails, bolts — insertion order, not alphabetical. If you need sorted keys, copy them to an array and sort.
String keys, number values
The pattern is the same for any key type. Strings are the usual choice for names. This listing tallies votes by candidate.
Example
const votes = new Map<string, number>();
votes.set("Ada", 0);
votes.set("Linus", 0);
votes.set("Ada", (votes.get("Ada") ?? 0) + 1);
votes.set("Ada", (votes.get("Ada") ?? 0) + 1);
votes.set("Linus", (votes.get("Linus") ?? 0) + 1);
console.log("Ada " + (votes.get("Ada") ?? 0));
console.log("Linus " + (votes.get("Linus") ?? 0));
if (!votes.has("Bjarne")) {
console.log("no Bjarne");
}Output is Ada 2, Linus 1, then no Bjarne.
Map versus a plain object
| array | Map | |
|---|---|---|
| Lookup | By index, or scan | By key with get |
| Order in a loop | The order you pushed | Insertion order of keys |
| Duplicate keys | Allowed as duplicate values | One entry per key |
| Missing get | — | undefined; use has or ?? |
A Record<string, number> object also maps names to numbers. Prefer Map when keys are added at run time, when you need .size, or when keys are not only strings (numbers, objects). Prefer an object literal for a tiny fixed set of known keys.
When a map is the wrong tool
If you only have a list and you always walk it from the front, keep an array. If you need unique values with no extra payload, a Set is the smaller type: just the keys. That is the next chapter.