
Immutable.js
Persistent collections for JavaScript (List, Map, Set, Record and more) built on hash array mapped tries and vector tries, with methods named like JavaScript’s own Array, Map and Set.
- What it is
- Purely functional data structures (hash array mapped tries)
- Type
- Open source
- Made by
- Immutable.js maintainers (started at Facebook by Lee Byron)
- License
- MIT (BSD before 4.0)
- Facts checked
- 9 October 2026
What it is
Immutable.js gives JavaScript the persistent collections of Clojure and Scala: List, Stack, Map, OrderedMap, Set, OrderedSet and Record. Methods that would mutate an array or map, such as push, set or splice, instead return a new collection, and the old one keeps working. Both share structure through hash map tries and vector tries, so an update copies a few small nodes instead of the whole collection. A lazy Seq chains map and filter without building intermediate collections.
Under the hood a Map starts as a flat array of up to eight entries and then becomes a 32-way hash array mapped trie: bitmap nodes that find a child by counting set bits, full 32-slot nodes when they fill up, and collision nodes for keys with equal hashes. Collections are values: a.equals(b) compares contents, while === only tests identity. An update that changes nothing returns the very same object, so === is a cheap “definitely unchanged” test for memoization and UI change detection. withMutations applies a batch of set or push calls to a temporary mutable copy and returns an immutable result, so building a large collection doesn’t allocate a new version per step.
Lee Byron started the library at Facebook in 2014, inspired by Phil Bagwell’s research. After 3.8.2 in October 2017 it went four years without a major release; 4.0.0 arrived in October 2021 with new maintainers, an MIT licence and better TypeScript types. It is actively maintained: 5.0.0 came out in November 2024, 5.1.9 in June 2026, and a 6.0.0 beta in August 2026.
Why teams pick it
- Copies are free and unchanged updates return the same object, so
===checks make memoization and change detection cheap - An API that mirrors ES2015
Array,MapandSet, with TypeScript definitions included withMutationsbatches many updates through one temporary mutable copy, the same way the library implements its own bulk operations- Lazy
Seqchains ofmapandfilteravoid intermediate collections
Watch out for
- Collections are not plain objects: code reads them with
getandgetIn, compares them with.equals(), and converts at the boundaries withfromJSandtoJS - Every non-batched update allocates new nodes; the README itself warns of “a minor performance penalty” for creating new objects
- A long pause between 3.8 (2016–2017) and 4.0 (2021), and 5.0 changed the TypeScript typing of
Map, a breaking change for TypeScript users
Update a nested value, share the rest, and batch a build · js
import { Map, List } from "immutable";
const v1 = Map({ user: Map({ name: "Ada", plan: "free" }), cart: List(["tea"]) });
const v2 = v1.setIn(["user", "plan"], "pro");
console.log(v1.getIn(["user", "plan"]), v2.getIn(["user", "plan"])); // free pro
console.log(v1.get("cart") === v2.get("cart")); // true: untouched branch is shared
console.log(v1.get("user") === v2.get("user")); // false: changed branch was copied
// a no-op update returns the same object, so === is a cheap "unchanged" test
console.log(v2.set("cart", v2.get("cart")) === v2); // true
console.log(v1.equals(Map({ user: Map({ name: "Ada", plan: "free" }), cart: List(["tea"]) }))); // true
// batch many updates through one temporary mutable copy
const big = List().withMutations((l) => { for (let i = 0; i < 100000; i++) l.push(i); });
console.log(big.size, big.get(99999)); // 100000 99999See it in a real stack
No architecture uses Immutable.js yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2014–2026
By 2014 Clojure and Scala had shown that persistent hash maps and vectors could be fast enough for everyday code, but JavaScript had nothing comparable. Lee Byron made the first commit to Immutable.js on 29 May 2014, under a Facebook copyright, and the README still thanks Phil Bagwell “for his inspiration and research in persistent data structures”. The npm name immutable came from Hugh Jackson, whose earlier package of that name is now unsupported; Facebook’s 2.0.0 was published in July 2014 and 3.0.0 in October.
The README pitched it for React and Flux apps. If application state is immutable, a component only needs to compare references to know whether its data changed, and an undo stack is just a list of old versions. Development slowed after 3.8: 3.8.2 shipped in October 2017 and 4.0.0 only in October 2021, when new maintainers joined and the project was relicensed from BSD to MIT. Version 5.0.0 followed in November 2024.
Why it’s built this way
- Hash tries and vector tries, as in Clojure and Scala
- Structural sharing lets an update copy only a few nodes, so persistent collections can be used everywhere instead of copying or caching data defensively.
- A JavaScript-first API
- Rather than a Lisp-style API, method names mirror ES2015
Array,MapandSet, and methods that would mutate return a new collection instead. - Value equality, with a reference shortcut
- Collections are values compared with
equals, but no-op updates return the existing object so===can still prove nothing changed, which suits memoization. - Transient batches with
withMutations - Building a collection one immutable step at a time creates garbage; a temporary mutable copy is safe as long as nobody else can see it, an argument the README quotes from Rich Hickey.
Timeline
- 2014
Lee Byron’s first commit (May); 2.0.0 on npm in July and 3.0.0 in October
- 2017
3.8.2, the last 3.x release for over eight years
- 2021
4.0.0: new maintainers, MIT licence, better TypeScript types
- 2024
5.0.0 tightens the TypeScript typing of
Map - 2026
5.1.9 in June and a 6.0.0 beta in August
- Immutable.js: first commit “Frist p0st” by Lee Byron (29 May 2014)
- Immutable.js LICENSE at v3.8.1 (BSD, Copyright 2014–2015 Facebook)
- Immutable.js README (introduction, thanks to Phil Bagwell and Hugh Jackson)
- npm registry: immutable (publish dates of every version)
- Immutable.js release notes: v4.0.0 (October 2021)
- Immutable.js release notes: v5.0.0 (November 2024)
Sources7 · facts checked 9 October 2026
- Immutable.js README (collections, structural sharing, equality, withMutations, Seq)
- Immutable.js source: src/Map.js (ArrayMapNode up to 8 entries, BitmapIndexedNode, HashArrayMapNode, HashCollisionNode)
- Immutable.js source: src/TrieUtils.ts (SHIFT = 5, 32-slot nodes)
- Immutable.js releases on GitHub
- Immutable.js release notes: v4.0.0 (MIT licence, new maintainers, TypeScript)
- Immutable.js release notes: v5.0.0 (TypeScript change to Map)
- npm registry: immutable (latest 5.1.9, published 29 June 2026)