MediumPro challengeJavaScriptTypeScript
deepFreeze<T> — Runtime Readonly
TypeScriptTypesObjects
Object.freeze only freezes the top level of an object. Nested objects remain mutable:
const config = Object.freeze({ db: { host: 'localhost' } });
config.db = {}; // ❌ frozen — throws in strict mode
config.db.host = 'other'; // ✅ nested object is NOT frozen — mutates silently!deepFreeze fixes this by recursively freezing all nested objects.
TypeScript angle
The compile-time equivalent is the DeepReadonly<T> utility type:
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
// deepFreeze is the runtime enforcement of DeepReadonly:
function deepFreeze<T extends object>(obj: T): Readonly<T>Note: TypeScript's built-in Readonly<T> is shallow (only marks top-level properties as readonly). DeepReadonly<T> is a custom recursive mapped type.
Implement
deepFreeze<T extends object>(obj: T): Readonly<T>
- Freeze
objwithObject.freeze - Recursively freeze all object-valued own properties
- Skip
nullvalues and already-frozen objects - Return the same object (mutated in place, just frozen)
Sample tests
Test #1flat object is fully frozen
Input: [{"a":1}]
Output: {"value":{"a":1},"isFrozen":true,"isDeepFrozen":true}
Test #2nested object is also frozen
Input: [{"a":{"b":1}}]
Output: {"value":{"a":{"b":1}},"isFrozen":true,"isDeepFrozen":true}
Test #3deeply nested 3 levels
Input: [{"a":{"b":{"c":42}}}]
Output: {"value":{"a":{"b":{"c":42}}},"isFrozen":true,"isDeepFrozen":true}
Test #4empty object
Input: [{}]
Output: {"value":{},"isFrozen":true,"isDeepFrozen":true}