Lodash _.invert() method
What you’ll learn
- How
_.invert(object)returns a new object with keys and values swapped. - Why duplicate values collide—and how iteration order decides the survivor.
- How non-string values are coerced when they become keys.
- When to reach for _.invertBy() instead to preserve duplicates.
Prerequisites
You should know that object keys are always strings (or symbols) in JavaScript. That single fact explains most of _.invert’s quirks.
- One-to-one mappings only: values must be unique, or use
_.invertBy. - Values become string keys: non-string values are coerced (e.g. numbers, booleans, objects).
- Pure function: always returns a new object; the input is never mutated.
Overview
_.invert walks the source’s own enumerable string-keyed properties and writes a new { value: key } pair for each one. Because object keys can’t be objects, values are stringified along the way. When two source keys share a value, the later iteration overwrites the earlier one—that’s the single most common surprise.
Swap, don’t mutate
A new object comes back. The original stays exactly as it was.
Lookup tables in one line
Turn a { name: code } map into { code: name } for fast reverse lookups.
Last-write-wins
Duplicate values overwrite. Reach for _.invertBy when collisions matter.
Syntax
_.invert(object) - object: any object whose own enumerable string-keyed values you want as the new keys.
- Returns: a brand-new object where the original values become keys and original keys become values.
Swap keys and values
The classic shape—a name-to-code map becomes a code-to-name map. Each lookup is now O(1) in either direction.
import invert from "lodash/invert";
const fruitColors = {
apple: "red",
banana: "yellow",
grape: "purple"
};
const colorToFruit = invert(fruitColors);
// -> { red: "apple", yellow: "banana", purple: "grape" }
colorToFruit.yellow;
// -> "banana"
fruitColors;
// -> { apple: "red", banana: "yellow", grape: "purple" }
// The original is untouched. Duplicate values collide (last wins)
When two source keys share a value, the second one overwrites the first. If you need to keep every original key, use _.invertBy().
import invert from "lodash/invert";
import invertBy from "lodash/invertBy";
const scores = { A: 1, B: 2, C: 1 };
invert(scores);
// -> { "1": "C", "2": "B" }
// A was overwritten by C because both map to 1.
invertBy(scores);
// -> { "1": ["A", "C"], "2": ["B"] }
// invertBy preserves every source key. Value coercion: numbers, booleans, objects
Every value is stringified when it becomes a key. That works fine for numbers, but turns every nested object into the string "[object Object]", which means all of them collide.
import invert from "lodash/invert";
const numericMap = { 1: "one", 2: "two", 3: "three" };
invert(numericMap);
// -> { one: "1", two: "2", three: "3" }
// The original 1, 2, 3 keys were already strings in JS object keys.
const mixed = { a: 1, b: true, c: null };
invert(mixed);
// -> { "1": "a", "true": "b", "null": "c" }
// All values were coerced to strings.
const nested = {
user: { id: 1 },
role: { id: 2 }
};
invert(nested);
// -> { "[object Object]": "role" }
// Both nested objects stringify the same way and collide. 📋 _.invert vs related helpers
| Topic | _.invert | _.invertBy | Manual Object.fromEntries |
|---|---|---|---|
| Returns | New flat object | New object of arrays | New flat object |
| Duplicate values | Last wins (lossy) | Grouped into arrays | Last wins (lossy) |
| Value coercion | To string | To string | To string |
| Custom transform | No | Yes (iteratee per value) | Yes (any map step) |
| Mutates input | No | No | No |
Use _.invert for one-to-one maps. Switch to _.invertBy the moment values can repeat or you need to bucket the keys. Native Object.fromEntries(Object.entries(obj).map(([k,v]) => [v,k])) is fine for small, controlled cases.
Pitfalls to avoid
Silent data loss with duplicates
No warning is thrown when keys collide. Validate uniqueness up front or switch to _.invertBy.
Nested objects all stringify to "[object Object]"
Inverting a map of nested objects collapses every entry under the same key. Flatten or extract a primitive first.
Numbers, booleans, and null become strings
After inverting, every key is a string. obj[1] still works because JS coerces, but TypeScript will treat the new key set as strings.
Iteration order decides who wins
Don’t rely on which duplicate “wins” if your source comes from JSON.parse or merged inputs—treat the choice as undefined for your business logic.
❓ FAQ
Summary
- Purpose: create a new object with keys and values swapped.
- Remember: values get stringified when they become keys; duplicates collapse with last-write-wins.
- Next: Lodash _.invertBy() for the duplicate-safe variant, or the official Lodash docs for _.invert.
Object keys are always strings (or symbols), so _.invert stringifies every value when it becomes a key—true becomes "true" and { a: 1 } becomes "[object Object]". The original keys, however, are kept as-is for the new values.
5 people found this page helpful
