Lodash _.assignInWith() method

Beginner
⏱️ 8 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.assignInWith(object, ...sources, customizer) layers _.assignIn with a per-key decision callback.
  • The customizer signature (objValue, srcValue, key, object, source) and the undefined fallback rule.
  • Why this is shallow even with a customizer—and when to delegate to _.mergeWith for depth.
  • Try each example in the editor (?tryit=1, 2, 3) with Lodash from a CDN.

Prerequisites

Read _.assignIn() first for the shared own-plus-inherited shallow semantics; this page focuses on the customizer.

  • Callbacks: the customizer is a plain function called per key—treat undefined returns as “skip”.
  • Immutability mindset: the customizer doesn’t change the shallow rule—return new objects yourself if you need fresh references for nested keys.

Overview

_.assignInWith is _.assignIn plus a callback. For every key Lodash would otherwise overwrite, it asks the customizer for a final value first. Return undefined and Lodash uses the incoming srcValue; return anything else and you decide.

Per-key control

Pick winners by key, combine numbers, concatenate strings, or guard against overwriting non-empty values.

undefined = fall through

Easy default: return undefined for keys you don’t care about and the source value wins as usual.

Still shallow

The walk stays one level deep—use _.mergeWith when you need recursive customization.

Syntax

javascript
_.assignInWith(object, [...sources], [customizer])
// alias: _.extendWith(object, [...sources], [customizer])
//
// customizer(objValue, srcValue, key, object, source) => any
  • object: destination; mutated in place.
  • sources: zero or more source objects; own and inherited enumerable string keys are visited left to right.
  • customizer: last argument; return undefined to accept the source value, anything else to override.
  • Returns: the (now-mutated) destination object.
  • Skipped: symbol keys; non-enumerable properties; nested depth (use _.mergeWith).
1

Per-key rule with undefined fallback

Combine two values for the key "b"; let every other key fall through to the source. Returning undefined is the “do what you normally do” signal.

javascript
import assignInWith from "lodash/assignInWith";

const target = { a: 1, b: 2 };
const source1 = { b: 3, c: 4 };
const source2 = { d: 5 };

function customizer(objValue, srcValue, key) {
  if (key === "b") {
    return (objValue || 0) * (srcValue || 1);
  }
  // undefined -> keep default behavior (srcValue wins)
}

assignInWith(target, source1, source2, customizer);
// target is now { a: 1, b: 6, c: 4, d: 5 }
Try it Yourself
2

“Don’t overwrite existing” pattern

A common defaults-style customizer: keep the destination’s value when it already exists, otherwise let the source fill the gap.

javascript
import assignInWith from "lodash/assignInWith";

const userPrefs = { theme: "dark", lang: undefined };
const defaults  = { theme: "light", lang: "en", fontSize: 14 };

function keepDefined(objValue, srcValue) {
  return objValue === undefined ? srcValue : objValue;
}

assignInWith(userPrefs, defaults, keepDefined);
// userPrefs -> { theme: "dark", lang: "en", fontSize: 14 }
Try it Yourself
3

Customizer also sees inherited keys

The “In” suffix means prototype keys are visited too—your callback runs for both own and inherited. Switch to _.assignWith when you only want own keys.

javascript
import assignInWith from "lodash/assignInWith";

function Source() {
  this.own = "instance";
}
Source.prototype.inherited = "prototype";

const seen = [];
function tag(objValue, srcValue, key) {
  seen.push(key);
  return String(srcValue).toUpperCase();
}

assignInWith({}, new Source(), tag);
// seen     -> ["own", "inherited"]
// result   -> { own: "INSTANCE", inherited: "PROTOTYPE" }
Try it Yourself

📋 _.assignInWith vs _.assignWith vs _.mergeWith

Topic_.assignInWith_.assignWith_.mergeWith
Customizer signature(objValue, srcValue, key, object, source)SameSame, plus stack for recursion
Own keysYesYesYes
Inherited keysYesNoNo
DepthShallowShallowRecursive
Aliases_.extendWith
Typical usePer-key rules on class instancesPer-key rules on plain objectsPer-key rules inside deep configs

Pick _.assignInWith when the source has meaningful prototype data and you need per-key logic; switch to _.mergeWith the moment you want depth.

Pitfalls to avoid

Customizer

Forgetting the undefined fallback

A customizer that always returns a value (even null or empty string) overwrites every key. Return undefined for keys you want to leave to the default rule.

Depth

Customizer is not recursion

The callback fires once per top-level key. Use _.mergeWith if you actually need to walk into nested objects.

Mutation

Destination is written in place

Pass {} as the first argument when callers share a reference and you need a fresh object.

❓ FAQ

Five arguments: (objValue, srcValue, key, object, source). objValue is what's currently on the destination, srcValue is the incoming value, key is the property name, and the last two are the destination and current source objects.
Lodash treats undefined as 'no opinion' and falls back to srcValue (the same precedence rule _.assignIn uses). Return any other value — including null or 0 — to override per key.
Same customizer signature and shallow shape. _.assignInWith walks own AND inherited enumerable string keys on each source; _.assignWith stays on own keys only.
Yes. _.extendWith is a documented alias of _.assignInWith and shares the implementation.
Not directly. It is still a shallow walk. For recursive combination of nested plain objects, use _.merge or _.mergeWith (the customizer form for deep work).
Use import assignInWith from "lodash/assignInWith"; for ESM or const assignInWith = require('lodash/assignInWith') in CommonJS.

Summary

Did you know?

_.assignInWith’s customizer is the only knob: return undefined and lodash falls back to srcValue; return anything else and that wins for the current key. The signature (objValue, srcValue, key, object, source) is shared by _.assignWith and _.mergeWith—learn it once.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful