UNPKG

@magic/types

Version:
127 lines (102 loc) 2.48 kB
// Written by Substack <3 import is from '../lib.js' /** * @overload * @param {unknown} a * @param {unknown} b * @returns {boolean} */ /** * @overload * @param {unknown} a * @returns {(c: unknown) => boolean} */ /** * @param {unknown} a * @param {unknown} [b] * @param {object} [options] * @param {boolean} [options.strict=false] * @param {boolean} [options.arrayOrderStrict=true] * @returns {boolean | ((c: unknown) => boolean)} */ export const equal = (a, b, options = {}) => { const { strict = false, arrayOrderStrict = false } = options // curry if (is.undefined(b)) { if (is.undefined(a)) { return true } return c => equal(a, c) } if (is.null(b)) { return a === b } // types must match if (typeof a !== typeof b) { return false } /* functions are handled by their toString value */ if (is.function(a) && is.function(b)) { return a.toString() === b.toString() } if (!is.object(a) || !is.object(b)) { return a === b } // identical 'prototype' property. if ('prototype' in a && 'prototype' in b) { return a.prototype === b.prototype } // real types must match too if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) { return false } // dates if (is.date(a)) { return a.toString() === b.toString() } // buffers if (is.buffer(a) && is.buffer(b)) { if (a.length !== b.length) { return false } for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) { return false } } return true } if (is.array(a) && is.array(b)) { if (!strict && !arrayOrderStrict) { a.sort() b.sort() } const allEqual = !a.some((v, i) => !equal(v, b[i])) return allEqual } if (is.objectNative(a) && is.objectNative(b)) { const aObj = a const bObj = b const ka = Object.keys(aObj) const kb = Object.keys(bObj) // having the same number of owned properties (keys incorporates hasOwnProperty) if (ka.length !== kb.length) { return false } if (!strict) { ka.sort() kb.sort() } // ~~~cheap key test for (let i = 0; i < ka.length; i++) { if (ka[i] !== kb[i]) { return false } } // equivalent values for every corresponding key, and // ~~~ possibly expensive deep test return !ka.some(key => !equal(aObj[key], bObj[key])) } return typeof a === typeof b } export default equal