Deep freezing recursively applies Object.freeze to an object and every nested object and array it references, so the whole structure becomes immutable at every level. The built-in Object.freeze only freezes the object you hand it — anything nested inside stays writable. Implement deepFreeze(value) to close that gap: freeze the value and walk into everything it points at, then return it.
deepFreeze(value: unknown): unknown
// freezes `value` and every object/array reachable through it, in place,
// then returns the SAME `value` (not a copy) so callers can chain.
const user = {
name: 'Ada',
roles: ['admin'],
address: { city: 'London' },
};
deepFreeze(user);
Object.isFrozen(user); // true
Object.isFrozen(user.address); // true — the nested object is frozen too
Object.isFrozen(user.roles); // true — and the array
user.address.city = 'Paris'; // ignored (or throws in strict mode)
user.address.city; // 'London' — unchanged
// Cycles must not cause infinite recursion:
const a = { name: 'a' };
a.self = a; // a points back at itself
deepFreeze(a); // must terminate, not blow the stack
Object.isFrozen(a); // true
a.self === a; // true — the cycle is preserved, just frozen
Object.freeze is shallow — it locks only the object passed to it. deepFreeze must recurse so that nested objects and arrays are frozen too.null, and undefined are already immutable. Return them as-is; do not try to recurse into them.a/b pair that reference each other, must not send the recursion into an infinite loop. Track the objects you have already visited (a WeakSet is the natural tool).deepFreeze does not clone. It mutates the objects it is given and returns the same top-level reference for chaining.push, pop, and index assignment, and their element objects must be frozen too.