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.
Recommended Method:
_.unset (Mutable)
To remove a property at an arbitrary nesting depth, Lodash provides
_.unset.
Syntax
_.unset(object, path)object: The target object to modify.path: The path of the property to unset, passed as a dot-notation string ('a.b.c') or an array of keys (['a', 'b', 'c']).
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)