Implement deepOmit() — Remove Keys from Nested Objects

deepOmit(obj, keys) removes specified keys at every level of a nested object or array. Build it with recursion handling both object and array nodes.

9 min read
JavaScript
Interview
Implementation
Objects

TABLE OF CONTENTS

deepOmit(obj, keys) removes the specified keys from an object at every level of nesting — including inside arrays. It's a recursive traversal problem that tests whether you remember arrays are objects too.


What is deepOmit()?

deepOmit(obj, keys) returns a new object with the specified keys stripped out at every level of nesting. If you omit "password" from a user object, it removes password at the top level, inside nested profile objects, and within objects inside arrays — recursively, exhaustively.

This is distinct from the shallow delete (delete obj.key or destructuring) which only operates on the top level. deepOmit walks the entire structure and prunes matching keys everywhere.

The implementation is a pre-order tree traversal that reconstructs the structure as it goes:

  • Plain objects — copy all entries except the omitted keys, recursively processing each value
  • Arrays — recursively process each element (arrays can contain objects with the targeted keys)
  • Primitives — returned as-is (they can't have keys to omit)

The subtlety that interviewers test: arrays are objects too, but you shouldn't filter array elements by key name — you should recurse into each element and omit keys within any nested objects inside the array.

Real-world use cases:

  • Sanitizing sensitive data — strip password, token, ssn from API responses before logging or sending to the client
  • API response trimming — remove internal fields (__typename, __v, internalId) from deeply nested GraphQL or MongoDB results
  • Form submission cleanup — omit UI-only keys (isEditing, selected) from form data before POST
  • Data export — remove circular reference markers or computed fields before serialization

This is a tree-map problem disguised as a utility function. It tests whether you can think recursively about structure transformation — applying the same operation at every level of an arbitrarily nested value.


The Problem

"Implement deepOmit(obj, keys) that returns a new object with the given keys removed from every level of nesting. If a value is an array, apply deep omit to each element."

deepOmit({ a: 1, b: { a: 2, c: 3 } }, ['a'])
// { b: { c: 3 } }

Thought Process

You're walking a tree and creating a modified copy. At each node:

  • Primitive → return as-is
  • Array → map each element through deepOmit
  • Object → create a new object excluding the target keys, then deepOmit each remaining value

The key insight: after stripping keys at the current level, you must recurse into the values in case they contain nested objects with the same keys.


Step 1 — Shallow Omit

Loading editor...


Step 2 — Deep Omit (Objects)

Loading editor...


Step 3 — Arrays of Objects

Loading editor...


Step 4 — Edge Cases

Key appears at multiple depths — already handled; the keySet.has(key) check runs at every object level.

Value is null — returned as-is (checked at the top of walk).

Empty arraysmap over zero elements returns []. Correct.

Key not in object — nothing to omit; the whole structure is returned identical (but cloned).

Nested key that's also a value{ x: { x: 1 } } with keys ['x']{}. The outer x is stripped; the inner x is never reached because the recursion only goes into remaining values.


Full Solution

Loading editor...


What Interviewers Are Testing

  • Recursive tree transformation — creating a structural copy while modifying at each level
  • Array handling in recursion — remembering that arrays contain objects that may also need omitting
  • Set for key lookup — using Set.has() for O(1) key checking instead of Array.includes()
  • Cloning semantics — returning a new object, not mutating the input

Complexity

TimeSpace
deepOmitO(N) — each value visited onceO(N) — new copy created

Interview Tips

  • Use a Set for keys — "I'll convert keys to a Set for O(1) lookup." This shows performance awareness.
  • Handle arrays before objectsArray.isArray check before the object branch, since arrays are objects.
  • Mention immutability — confirm with the interviewer that the function should return a new copy, not mutate the input.
  • Think aloud about the recursion — "At each level, I strip the keys, then recurse into the remaining values in case they contain the same keys at a deeper level."

Related Questions


Let's Connect

© 2026 Naveen Karthik // Built with React & MUI