TypeScript

Using a Typed Map in TypeScript: Entries, Iteration, and When to Choose It

Create and use a typed Map in TypeScript, including entries, iteration, values, and the bracket-assignment trap.

Editorial illustration for Using a Typed Map in TypeScript: Entries, Iteration, and When to Choose It

Choose a Map when keyed data needs collection operations: checking whether a key exists, deleting an entry, reading the number of entries, or iterating them in insertion order. The important distinction is that a Map stores entries through its API. It may look object-like in a console, but assigning a property with brackets does not add an entry.

Create a Map with key and value types

In Map<string, number>, the first type argument describes keys and the second describes values. You can start empty or pass an array of key-value pairs to the constructor:

const emptyCounts: Map<string, number> = new Map<string, number>();

const counts: Map<string, number> = new Map<string, number>([
  ["apple", 3],
  ["pear", 5],
]);

console.log(counts.get("apple")); // 3
console.log(counts.get("pear")); // 5
console.log(counts.size); // 2

The constructor creates two entries here, so size is 2. This is a JavaScript collection with TypeScript key and value types on the variable; the type arguments are not a runtime check on data entering your application. For the constructor form and generic arguments, see MDN’s Map constructor example and this typed initialization example.

Change entries through the Map API

Continue with counts from above. set adds an entry or updates one with the same key; get reads a value, has checks membership, delete removes an entry, and size counts entries.

console.log(counts.has("pear")); // true

counts.set("plum", 8);
console.log(counts.get("plum")); // 8
console.log(counts.size); // 3

counts.delete("pear");
console.log(counts.has("pear")); // false
console.log(counts.size); // 2

Use has when the question is whether a key is present. Use get when you need its value. Keeping those questions distinct makes the intent of a lookup easier to read, particularly in code that also adds and removes entries. The operations above are part of the Map API, not special TypeScript syntax.

There is one easy mistake when working with string keys. This separate example deliberately gives the variable an ordinary bonus property so the bracket assignment is valid TypeScript:

const wrongMap: Map<string, number> & { bonus?: number } =
  new Map<string, number>();

wrongMap["bonus"] = 99;
console.log(wrongMap["bonus"]); // 99: an object property
console.log(wrongMap.has("bonus")); // false: not a Map entry
console.log(wrongMap.size); // 0

The extra property in the variable’s type does not change what the assignment does. Brackets set a property on the Map object; they do not call set. Other Map operations will not treat that property as an entry. If bonus should participate in lookups and iteration, write wrongMap.set("bonus", 99) instead. MDN documents this distinction because the property can otherwise appear to work until code calls has or delete.

Iterate entries and collect values

A Map is directly iterable as key-value pairs. After the earlier set and delete, counts contains apple followed by plum:

for (const [fruit, count] of counts) {
  console.log(`${fruit}: ${count}`);
}
// apple: 3
// plum: 8

const values: number[] = Array.from(counts.values());
console.log(values); // [3, 8]

Map iteration follows insertion order, which is why apple appears before the later addition of plum. values() provides the values in that order, and Array.from collects them into an array. If you need just the keys, keys() is available; entries() provides key-value pairs explicitly. Direct iteration is a compact choice when you need both parts of each entry.

Decide whether you need entries or properties

A Record<string, number> describes an object with string-keyed number properties; it is not another spelling for a runtime Map. If your data is meant to be accessed as object properties, keep it as an object. If callers need set, has, delete, size, or entry iteration in insertion order, choose Map and use its methods consistently. The difference matters most at the boundary between those styles: object[key] = value is normal property access, but map[key] = value is not a substitute for map.set(key, value). For the object-side distinction, see the Record and Map comparison.

Find a note

Search by topic, title, or keyword.