Created
June 29, 2024 07:26
-
-
Save innateessence/be0eab724b657b392dd22ad042333a2c to your computer and use it in GitHub Desktop.
Javascript is hacky and I wanted a convenient way to compare objects in a predictable way so I wrote this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Object comparison lib/functions. | |
// These are intended to behave as one would expect vanilla JS to behave if JS wasn't so hacky. | |
export const isObject = (a: any): boolean => { | |
// Strictly check if something is an object. | |
// Javascript is such a hacky language... -_- | |
return typeof a === "object" && a !== null && !Array.isArray(a); | |
}; | |
export const isObjectOrArray = (a: any): boolean => { | |
return isObject(a) || Array.isArray(a); | |
}; | |
export const areBothObjects = (a: any, b: any): boolean => { | |
return isObjectOrArray(a) && isObjectOrArray(b); | |
}; | |
export const areBothSameType = (a: any, b: any): boolean => | |
typeof a === typeof b; | |
export const objectIsEmpty = (a: Record<string, any>): boolean => { | |
return objectsAreEqual(a, {}); | |
}; | |
export const objectsKeysAreEqualLength = ( | |
a: Record<string, any>, | |
b: Record<string, any>, | |
): boolean => { | |
// This function will check if two objects have the same number of keys at root level | |
if (!areBothObjects(a, b)) { | |
return false; | |
} | |
if (Object.keys(a).length !== Object.keys(b).length) { | |
return false; | |
} | |
return true; | |
}; | |
export const objectValuesAreEqualLength = ( | |
a: Record<string, any>, | |
b: Record<string, any>, | |
): boolean => { | |
// This function will check if two objects have the same number of values at root level | |
if (!areBothObjects(a, b)) { | |
return false; | |
} | |
if (Object.values(a).length !== Object.values(b).length) { | |
return false; | |
} | |
return true; | |
}; | |
export const objectsAreEqual = ( | |
a: Record<string, any>, | |
b: Record<string, any>, | |
): boolean => { | |
// This function will recursively traverse two objects to check | |
// if two deeply nested (or flat) objects are equal based on their keys & values | |
// This behaves as someone would expect `obj1 === obj2` would behave if JS wasn't so hacky. | |
if (!areBothSameType(a, b)) { | |
return false; | |
} | |
if (!objectsKeysAreEqualLength(a, b)) { | |
return false; | |
} | |
if (!objectValuesAreEqualLength(a, b)) { | |
return false; | |
} | |
// begin recursion | |
for (let prop in a) { | |
if (a.hasOwnProperty(prop)) { | |
if (b.hasOwnProperty(prop)) { | |
if (typeof a[prop] === "object") { | |
if (!objectsAreEqual(a[prop], b[prop])) { | |
return false; | |
} | |
} else { | |
if (a[prop] !== b[prop]) { | |
return false; | |
} | |
} | |
} else { | |
return false; | |
} | |
} | |
} | |
return true; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment