How to Use a TypeScript Map: ES6 Collections with Static Typing

A TypeScript Map is a strongly-typed wrapper around JavaScript's ES6 Map collection that enforces type safety for keys and values through generic parameters K and V defined in the standard library declaration files.

The TypeScript compiler adds static type checking to JavaScript's native ES6 Map through declaration files found in the microsoft/TypeScript repository. These type definitions allow developers to create maps with compile-time guarantees that keys and values match specified types, preventing runtime errors while maintaining full compatibility with the underlying JavaScript runtime.

Core TypeScript Map Interface Declaration

In src/lib/es2015.collection.d.ts, TypeScript defines the Map<K, V> interface using generic parameters where K represents the key type and V represents the value type. This interface describes the exact shape of the runtime ECMAScript 2015 Map object while adding compile-time type enforcement.

interface Map<K, V> {
    /** Returns the number of entries in the map. */
    readonly size: number;

    /** Adds a new entry or updates an existing one. */
    set(key: K, value: V): this;

    /** Retrieves the value for a given key – returns undefined if the key is absent. */
    get(key: K): V | undefined;

    /** Returns true if the map contains the given key. */
    has(key: K): boolean;

    /** Removes an entry. Returns true if the entry existed. */
    delete(key: K): boolean;

    /** Removes all entries. */
    clear(): void;

    /** Returns an iterator over the map’s keys. */
    keys(): IterableIterator<K>;

    /** Returns an iterator over the map’s values. */
    values(): IterableIterator<V>;

    /** Returns an iterator over [key, value] tuples. */
    entries(): IterableIterator<[K, V]>;

    /** Default iterator – same as `entries()`. */
    [Symbol.iterator](): IterableIterator<[K, V]>;

    /** Executes a callback for each entry. */
    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
}

Key Methods and Properties

  • get(key: K): Returns V | undefined because JavaScript Map returns undefined for missing keys, forcing explicit handling of absent values.
  • set(key: K, value: V): Returns this to enable method chaining while enforcing type constraints.
  • has(key: K): Returns boolean without consuming the value, useful for existence checks.
  • delete(key: K): Returns boolean indicating whether the key existed before deletion.
  • readonly size: Property tracking entry count, marked readonly as mutation only occurs through set and delete.

MapConstructor and Map Creation

TypeScript models the JavaScript Map constructor through the MapConstructor interface in the same declaration file. This interface describes how to instantiate maps from iterables of tuples or create empty typed collections.

interface MapConstructor {
    /** Creates a new empty map. */
    new <K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;

    /** The prototype property of the Map constructor. */
    readonly prototype: Map<any, any>;

    /** Returns a new map that contains the same entries as the iterable. */
    from<K, V>(iterable: Iterable<[K, V]>): Map<K, V>;
}
declare const Map: MapConstructor;

The generic constructor allows initialization with explicit types: new Map<string, number>() creates an empty map where the compiler ensures string keys always map to number values.

Practical TypeScript Map Examples

The following examples demonstrate type-safe Map usage according to the Microsoft/TypeScript source definitions:

Creating and Mutating Typed Maps

// 1️⃣ Creating a typed map
const scores = new Map<string, number>();

// Adding entries – type-checked at compile time
scores.set('Alice', 42);
scores.set('Bob', 37);

// 2️⃣ Reading values – the return type is `number | undefined`
const aliceScore = scores.get('Alice'); // 42
const unknownScore = scores.get('Eve');  // undefined

Iterating Over Entries

// 3️⃣ Iterating over a map
for (const [name, score] of scores) {
    console.log(`${name} scored ${score}`);
}
// Output:
// Alice scored 42
// Bob scored 37

Using Objects as Keys

// 4️⃣ Using a map with object keys
interface Point { x: number; y: number }
const pointMap = new Map<Point, string>();
const p1: Point = { x: 0, y: 0 };
pointMap.set(p1, 'origin');
console.log(pointMap.get(p1)); // "origin"

Initializing from Arrays

// 6️⃣ Initialising from an array of entries
const colors = new Map<string, string>([
    ['red', '#ff0000'],
    ['green', '#00ff00'],
    ['blue', '#0000ff'],
]);
console.log(colors.get('green')); // "#00ff00"

ReadonlyMap for Immutable Collections

TypeScript provides a ReadonlyMap<K, V> interface (defined in src/lib/es2015.collection.d.ts) that exposes the same read methods as Map but omits mutating methods (set, delete, clear). This pattern is essential for function parameters where you want to prevent modification of the passed map.

// 5️⃣ Read-only view – useful for API boundaries
function logAll(map: ReadonlyMap<string, number>) {
    map.forEach((value, key) => console.log(`${key}: ${value}`));
}
logAll(scores); // OK
// scores.set('Eve', 10); // ❌ compile-time error outside this scope

Attempting to call mutating methods on a ReadonlyMap parameter results in a compile-time error, enforcing immutability at the type level.

Source Files in the TypeScript Repository

The type definitions for Map are distributed across lib files that ship with the compiler:

  • src/lib/es2015.collection.d.ts: Core ES2015 Map interface and MapConstructor definitions used when targeting ES2015 or higher.
  • src/lib/esnext.collection.d.ts: Extended collection typings for newer ECMAScript targets, including additional iterator protocol symbols.
  • src/lib/lib.es2022.d.ts: Aggregates and re-exports collection types for specific lib references, ensuring /// <reference lib="es2022"/> pulls the correct Map shape.

These files contain only type declarations—they describe the contract that your TypeScript code must satisfy, while the actual Map implementation is provided by the JavaScript engine at runtime.

Summary

  • TypeScript Map types are declared in src/lib/es2015.collection.d.ts using generic interfaces Map<K,V> and MapConstructor that mirror the JavaScript ES6 Map API.
  • The K and V generic parameters enforce compile-time type safety for all keys and values stored in the map, preventing type mismatches before execution.
  • Method signatures like get(), set(), and has() are typed to ensure operations use correct types, with get() returning V | undefined to handle missing keys safely.
  • ReadonlyMap<K,V> provides an immutable view suitable for function parameters and API boundaries where mutation must be prevented.
  • At runtime, TypeScript compiles down to JavaScript's native ES6 Map implementation, incurring no performance overhead from the type layer.

Frequently Asked Questions

What is the difference between a TypeScript Map and a JavaScript Map?

There is no runtime difference—TypeScript Map types are compile-time annotations that describe JavaScript's native ES6 Map. The TypeScript compiler uses declaration files like src/lib/es2015.collection.d.ts to verify that your code respects the generic type parameters K and V, then erases these types when generating JavaScript, leaving the standard Map implementation to handle execution.

How do you initialize a TypeScript Map with data?

Use the Map constructor with an array of key-value tuples and explicit generic type parameters: new Map<string, number>([['Alice', 42], ['Bob', 37]]). TypeScript validates that each tuple matches the declared key and value types, ensuring the map is correctly typed from initialization.

Can you use objects as keys in a TypeScript Map?

Yes, the Map interface accepts any type for K, including objects and functions. When you declare Map<Point, string>, TypeScript allows object references as keys while ensuring associated values match the string type, leveraging JavaScript's reference-based equality for object keys.

Why does a TypeScript Map return undefined for missing keys?

The get(key: K) method signature returns V | undefined because the JavaScript Map specification mandates returning undefined for absent keys. This union type forces developers to handle the undefined case explicitly in TypeScript, preventing null pointer exceptions that might occur if the type system assumed a value always existed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s https://instagit.com/install.md

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client