TypeScript-first utility to check deep immutability in JavaScript objects
Tiny zero-dependency library to detect and assert deep immutability.
Works with plain objects, arrays, Maps, Sets, Dates, and nested structures.
Ships with full TypeScript support and ESM-only build.
- TypeScript-first — strong type guards like
value is DeepImmutable<T> - Deep immutability checks — recursive checks across nested structures
- Helpful errors —
assertImmutableshows the exact path of mutability - Zero dependencies — small, fast, tree-shakable
- Modern packaging — ESM, Node 18+, Deno, Bun
npm install is-deep-immutableimport { isDeepImmutable, assertImmutable } from 'is-deep-immutable';
const data = {
users: [{ id: 1, name: 'Alice' }],
metadata: new Map([['version', '1.0.0']]),
tags: new Set(['production'])
};
// Check if deeply immutable
console.log(isDeepImmutable(data)); // false
// Manually freeze for testing
const frozen = Object.freeze({
users: Object.freeze(data.users.map(u => Object.freeze(u))),
metadata: Object.freeze(data.metadata),
tags: Object.freeze(data.tags)
});
console.log(isDeepImmutable(frozen)); // true
// Assert immutability (throws if not)
assertImmutable(frozen); // ✓ passes
assertImmutable(data); // ✗ throws with detailed pathType guard that checks if a value is deeply immutable. Returns true for primitives and recursively frozen objects.
isDeepImmutable(42); // true
isDeepImmutable('hello'); // true
isDeepImmutable({}); // false
isDeepImmutable(Object.freeze({})); // trueAsserts that a value is deeply immutable. Throws with the exact path of mutability if not.
assertImmutable({ mutable: true });
// Error: Value is not immutable at path "root": Object is not frozen
assertImmutable({ nested: { mutable: true } });
// Error: Value is not immutable at path "nested": Object is not frozenFull TypeScript support with the DeepImmutable<T> utility type:
type DeepImmutable<T> = T extends (infer U)[]
? ReadonlyArray<DeepImmutable<U>>
: T extends Map<infer K, infer V>
? ReadonlyMap<DeepImmutable<K>, DeepImmutable<V>>
: T extends Set<infer U>
? ReadonlySet<DeepImmutable<U>>
: T extends object
? { readonly [K in keyof T]: DeepImmutable<T[K]> }
: T;- Primitives:
string,number,boolean,null,undefined,symbol,bigint - Objects: Plain objects with recursive property checking
- Arrays: Recursive element checking
- Maps: Key and value immutability checking
- Sets: Element immutability checking
- Dates: Treated as immutable when frozen
- Circular references: Handled safely without infinite recursion
MIT