Implement deepMap(value, transform) — walk an arbitrarily nested structure (arrays and plain objects) and apply transform to every leaf value, returning a new structure with the same shape but with each leaf replaced by transform(leaf). A leaf is anything that is not a plain object or array: numbers, strings, booleans, null, undefined, Date, functions, class instances — they all reach transform untouched. Think of it as Array.prototype.map generalised across heterogeneous trees instead of a flat list.
// Returns a NEW value with the same shape as `value`, where every leaf
// has been replaced by transform(leaf). Containers (arrays and plain
// objects) are recreated fresh; nothing in the result aliases the input.
function deepMap<T>(value: T, transform: (leaf: unknown) => unknown): T;
// Flat object — every value goes through transform.
deepMap({ a: 1, b: 2, c: 3 }, (x) => x * 10);
// → { a: 10, b: 20, c: 30 }
// Nested object — the recursion descends; only the LEAVES are mapped.
deepMap({ user: { name: 'ada', age: 30 } }, (x) =>
typeof x === 'string' ? x.toUpperCase() : x,
);
// → { user: { name: 'ADA', age: 30 } }
// Array of primitives.
deepMap([1, 2, 3, 4], (x) => x * x);
// → [1, 4, 9, 16]
// Mixed — object containing arrays containing objects.
deepMap(
{ items: [{ qty: 1 }, { qty: 2 }], total: 3 },
(x) => (typeof x === 'number' ? x + 100 : x),
);
// → { items: [{ qty: 101 }, { qty: 102 }], total: 103 }
Array.isArray) or a plain object literal. Everything else — primitives, Date, Map, functions, class instances — is a leaf. transform is called on the leaf as a whole; you never recurse into a Date.null is a leaf. typeof null === 'object', but null has no properties — pass it to transform rather than treating it like a container.Date and other class instances are leaves. Even though typeof new Date() === 'object', you do not recurse into its internals; transform receives the Date itself.WeakMap-based extension.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.