Lodash pickBy: Differentiating Undefined and Null
Lodash's _.pickBy method creates an object composed of
properties that satisfy a specific predicate function, making it an
effective tool for separating strictly undefined properties
from explicit null values. Because JavaScript treats both
null and undefined as falsy and loosely equal
(null == undefined), default checks often conflate the two.
By using custom predicates leveraging strict inequality or dedicated
type-checking utilities like _.isUndefined and
_.isNull, _.pickBy cleanly isolates these
distinct property states during serialization or state sanitization.
The Default Behavior of
_.pickBy
When called without a custom predicate, _.pickBy
defaults to _.identity, which evaluates the truthiness of
each property value:
const _ = require('lodash');
const data = {
active: true,
name: null,
description: undefined,
count: 0
};
// Default behavior removes all falsy values, including null, undefined, and 0
const result = _.pickBy(data);
// Output: { active: true }Because _.identity removes all falsy values, both
null and undefined are stripped
indiscriminately.
Preserving
null While Removing undefined
In APIs and databases, null often indicates intentional
emptiness or a reset state, whereas undefined signals an
absent or unprovided field. To drop strictly undefined keys
while retaining null, supply a predicate that explicitly
checks for strict inequality against undefined or uses
_.isUndefined:
const payload = {
id: 101,
middleName: null, // Explicitly set to empty
nickname: undefined // Missing / omitted
};
// Filter out only undefined values
const withoutUndefined = _.pickBy(payload, (value) => value !== undefined);
// Alternative using Lodash utilities:
// const withoutUndefined = _.pickBy(payload, _.negate(_.isUndefined));
console.log(withoutUndefined);
// Output: { id: 101, middleName: null }In this implementation, middleName is kept intact
because null !== undefined evaluates to
true.
Preserving
undefined While Removing null
Conversely, if the objective is to clean out explicitly
null attributes while retaining undefined
placeholders, apply a strict check against null or utilize
_.isNull:
const payload = {
id: 101,
middleName: null,
nickname: undefined
};
// Filter out only null values
const withoutNull = _.pickBy(payload, (value) => value !== null);
// Alternative using Lodash utilities:
// const withoutNull = _.pickBy(payload, _.negate(_.isNull));
console.log(withoutNull);
// Output: { id: 101, nickname: undefined }Under the Hood: Why Strict Differentiation Works
Under the hood, _.pickBy iterates over an object’s own
and inherited enumerable string-keyed properties using an internal loop
(similar to baseForOwn). For every entry, it executes:
if (predicate(value, key)) {
result[key] = value;
}Because Lodash passes the exact reference of value
directly to the predicate, JavaScript's strict identity operator
(===) or Lodash’s type checkers
(Object.prototype.toString.call via _.isNull /
value === undefined via _.isUndefined) prevent
type coercion. This guarantees that explicit null
assignments are never conflated with missing or undefined
keys.