Search code examples
javascriptlodashequality

How to treat missing & undefined properties as equivalent in Lodash's isEqualWith


I'm fighting with a custom comparison functions for Lodash's _.isEqualWith. I'd like a function such that this is works:

const comparisonFunc = /* ...TBC... */

// Should be true:
_.isEqualWith({ a: undefined }, { }, comparisonFunc);

// Should still be false, as normal:
_.isEqualWith({ a: undefined }, { a: 123 }, comparisonFunc);

// Should still be false, as normal:
_.isEqualWith([undefined], [ ], comparisonFunc);

I.e. for any object in the comparison (recursively), properties set to undefined should be treated as if they didn't exist.


Solution

  • It's not as simple as I'd like, but I found a solution for this:

    const comparisonFunc = (a, b) => {
        if (_.isArray(a) || _.isArray(b)) return;
        if (!_.isObject(a) || !_.isObject(b)) return;
    
        if (!_.includes(a, undefined) && !_.includes(b, undefined)) return;
    
        // Call recursively, after filtering all undefined properties
        return _.isEqualWith(
            _.omitBy(a, (value) => value === undefined),
            _.omitBy(b, (value) => value === undefined),
            comparisonFunc
        );
    }
    
    
    // Should be true:
    _.isEqualWith({ a: undefined }, { }, comparisonFunc); // = true
    
    // Should still be false, as normal:
    _.isEqualWith({ a: undefined }, { a: 123 }, comparisonFunc); // = false
    
    // Should still be false, as normal:
    _.isEqualWith([undefined], [ ], comparisonFunc); // = false
    

    Happy to accept other answers if anybody has something simpler or better though :-)