Duplicate Keys in Lodash mapKeys Explained

When using the _.mapKeys function in Lodash, returning identical string keys for multiple properties causes the subsequent keys to overwrite the earlier ones. Because standard JavaScript objects cannot maintain duplicate keys, Lodash assigns the mapped key to the accumulator object sequentially, meaning the final object will only retain the value of the last evaluated property that produced that duplicate key, effectively causing earlier associated values to be lost.

The Overwriting Mechanism

The _.mapKeys method iterates over an object’s own enumerable string-keyed properties, applying a transformation function to each key to produce a new key while keeping the original values intact. Internally, Lodash constructs a new empty object and assigns each transformed key along with its original value using standard object property assignment:

result[newKey] = value;

Because of this direct assignment, when multiple source properties evaluate to the same target key, the property assignment quietly overrides whichever value was previously mapped to that key.

Code Example

Consider an example where two distinct properties produce the same key after applying the iteratee function:

const _ = require('lodash');

const users = {
  a: { name: 'Alice', role: 'admin' },
  b: { name: 'Bob', role: 'editor' },
  c: { name: 'Charlie', role: 'admin' }
};

// Mapping keys to the user's role
const byRole = _.mapKeys(users, (value) => value.role);

console.log(byRole);
// Output:
// {
//   admin: { name: 'Charlie', role: 'admin' },
//   editor: { name: 'Bob', role: 'editor' }
// }

In this case, both property a and property c returned the key 'admin'. Because c was processed after a, its value overrode the entry for a.

Property Iteration Order

The specific value that persists depends entirely on the traversal order of the source object's keys. Under the ECMAScript specification, standard string keys are traversed in the chronological order of their creation (insertion order), while integer-like keys are traversed first in ascending numerical order. Lodash follows this standard iteration behavior. Consequently, the property inserted or defined latest among the conflicting set will be the one retained.

Alternatives for Preserving Conflicting Values

If preserving data across duplicate mapped keys is required, _.mapKeys is not the appropriate utility. Instead, use patterns that group matching keys together: