Remove Deep Properties with Lodash Omit

This guide explains how to remove deeply nested properties from JavaScript objects using the Lodash utility library. While developers frequently attempt to use _.omit for nested keys, Lodash v4+ does not support deep property paths within _.omit. This article covers the syntax limitations of _.omit and details the correct, idiomatic methods to delete nested properties mutably and immutably using Lodash.


The Limitation of _.omit with Deep Paths

In older versions of Lodash, _.omit supported deep property paths using dot notation. However, in Lodash version 4.0.0 and later, _.omit only accepts shallow, top-level property keys.

Attempting to run the following syntax will not delete the nested property:

const _ = require('lodash');

const user = {
  id: 1,
  profile: {
    name: 'Alice',
    age: 30
  }
};

// This DOES NOT work in Lodash v4+
const result = _.omit(user, ['profile.age']);
console.log(result);
// Output still includes profile.age: { id: 1, profile: { name: 'Alice', age: 30 } }

Lodash treats 'profile.age' as a literal top-level key rather than a nested path.


To remove a property at an arbitrary nesting depth, Lodash provides _.unset.

Syntax

_.unset(object, path)

Example

const _ = require('lodash');

const user = {
  id: 1,
  profile: {
    name: 'Alice',
    age: 30
  }
};

_.unset(user, 'profile.age');

console.log(user);
// Output: { id: 1, profile: { name: 'Alice' } }

Note: _.unset mutates the original object in place.


Immutable Deep Omit: _.cloneDeep + _.unset

Because _.omit is designed to be immutable (returning a shallow copy without altering the source object), the standard way to achieve an immutable deep omit in Lodash is to clone the object before calling _.unset.

Example Implementation

const _ = require('lodash');

function deepOmit(object, paths) {
  const cloned = _.cloneDeep(object);
  const pathList = Array.isArray(paths) ? paths : [paths];

  pathList.forEach((path) => {
    _.unset(cloned, path);
  });

  return cloned;
}

const user = {
  id: 101,
  details: {
    credentials: {
      passwordHash: 'secret123',
      token: 'xyz-token'
    },
    status: 'active'
  }
};

// Remove single or multiple nested properties immutably
const sanitizedUser = deepOmit(user, [
  'details.credentials.passwordHash',
  'details.credentials.token'
]);

console.log(sanitizedUser);
// Output: { id: 101, details: { credentials: {}, status: 'active' } }
console.log(user.details.credentials.passwordHash); 
// Output: 'secret123' (Original object remains unchanged)