Skip to content

Instantly share code, notes, and snippets.

@innateessence
Created June 29, 2024 07:26
Show Gist options
  • Save innateessence/be0eab724b657b392dd22ad042333a2c to your computer and use it in GitHub Desktop.
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
// 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