Lodash isDate and Invalid NaN Date Instances
In JavaScript, managing date objects often leads to subtle bugs when
a Date instance is created with invalid arguments,
resulting in an "Invalid Date" object whose .getTime()
returns NaN. While developers often reach for utility
libraries to sanitize inputs, Lodash’s _.isDate function
serves primarily as an object-type guard rather than a temporal validity
validator. This article explains how _.isDate evaluates
date instances, why it allows NaN timestamps to pass, and
the exact patterns required to ensure a date is both an instance of
Date and temporally valid.
Type Guarding vs. Validity Checking
Lodash’s _.isDate is designed to verify whether an input
is an object classified as a Date. Internally, it inspects
the internal [[Class]] tag of the value using
Object.prototype.toString.call(value):
function isDate(value) {
return isObjectLike(value) && baseGetTag(value) == '[object Date]';
}Because of this design, _.isDate does not verify if the
internal timestamp is valid. An invalid date created via
new Date('invalid-string') is still fundamentally a
Date instance. As a result:
const invalidDate = new Date('not a real date');
console.log(_.isDate(invalidDate)); // true
console.log(invalidDate.getTime()); // NaN_.isDate protects your code from primitive types, null
references, plain objects, or strings masquerading as dates. However, it
does not prevent an instance from yielding NaN when queried
for its time.
How to Protect Against Invalid Date Instances
To completely guard an application from processing NaN
time values, _.isDate must be paired with a check against
the instance's numeric representation.
Method 1: Combining
_.isDate with .getTime()
The most direct approach checks that the object is a recognized
Date and that its internal epoch time is a valid
number:
function isValidDate(value) {
return _.isDate(value) && !Number.isNaN(value.getTime());
}
isValidDate(new Date()); // true
isValidDate(new Date('invalid-string')); // false
isValidDate('2026-01-01'); // falseCalling .getTime() returns the number of milliseconds
since January 1, 1970, UTC. If the date is invalid, it returns
NaN. Number.isNaN() accurately detects this
state, ensuring only valid dates proceed.
Method 2: Coercion via
Number()
Another common pattern involves numeric coercion:
function isValidDate(value) {
return _.isDate(value) && !isNaN(Number(value));
}When a Date object is passed to Number(),
JavaScript internally invokes Date.prototype.valueOf(),
which returns the same value as .getTime().
Summary
Lodash's _.isDate protects exclusively against type
mismatches by verifying the internal [object Date] tag. It
does not protect against instances that return NaN for
their time. To ensure that an object is both a Date
instance and represents a valid point in time, always combine
_.isDate(value) with
!Number.isNaN(value.getTime()).