Last active
March 5, 2025 14:11
-
-
Save colelawrence/3349ac4218d25e7c997a7d2bd31193d0 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| /** | |
| * Check the equality of anything | |
| * | |
| * **Example return** | |
| * | |
| * { "permissions.foo": [{}, { "a": 1 }] } | |
| * | |
| * @param {any} obj1 | |
| * @param {any} obj2 | |
| * @returns {{ [path: string]: [any, any] }} list of differences in tuple [<path>, <a>, <b>] | |
| */ | |
| function deepDiff(obj1, obj2) { | |
| return deepDiffR(obj1, obj2, []).reduce( | |
| (acc, [path, a, b]) => ({ | |
| ...acc, | |
| [path.join('.')]: [a, b], | |
| }), | |
| {}, | |
| ); | |
| } | |
| /** | |
| * @internal | |
| * Check the equality of anything | |
| * @param {any} obj1 | |
| * @param {any} obj2 | |
| * @param {(string|number|symbol)[]} path | |
| * @returns {[(string|number|symbol)[], any, any][]} list of differences in tuple [<path>, <a>, <b>] | |
| */ | |
| function deepDiffR(obj1, obj2, path) { | |
| if (obj1 === obj2) { | |
| return []; | |
| } | |
| if (isObject(obj1) && isObject(obj2)) { | |
| if (Object.keys(obj1).length !== Object.keys(obj2).length) { | |
| return [[path, obj1, obj2]]; | |
| } | |
| const diffs = []; | |
| for (const prop in obj1) { | |
| diffs.push(...deepDiffR(obj1[prop], obj2[prop], [...path, prop])); | |
| } | |
| return diffs; | |
| } | |
| return [[path, obj1, obj2]]; | |
| } | |
| /** | |
| * @internal | |
| * @param {any} obj | |
| * @returns {obj is {[key: string | number | symbol]: any}} | |
| */ | |
| function isObject(obj) { | |
| return typeof obj === 'object' && obj != null; | |
| } |
This file contains hidden or 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
| /** | |
| * Check the equality of anything | |
| * | |
| * **Example return** | |
| * | |
| * { "permissions.foo": [{}, { "a": 1 }] } | |
| * | |
| * @returns list of differences in tuple [<path>, <a>, <b>] | |
| */ | |
| export function deepDiff(obj1: any, obj2: any): { [path: string]: [any, any] } { | |
| return deepDiffR(obj1, obj2, []).reduce( | |
| (acc, [path, a, b]) => ({ | |
| ...acc, | |
| [path.join(".")]: [a, b], | |
| }), | |
| {} | |
| ); | |
| } | |
| /** | |
| * @internal | |
| * Check the equality of anything | |
| * @returns list of differences in tuple [<path>, <a>, <b>] | |
| */ | |
| function deepDiffR( | |
| obj1: any, | |
| obj2: any, | |
| path: (string | number | symbol)[] | |
| ): [(string | number | symbol)[], any, any][] { | |
| if (obj1 === obj2) { | |
| return []; | |
| } | |
| if (isObject(obj1) && isObject(obj2)) { | |
| if (Object.keys(obj1).length !== Object.keys(obj2).length) { | |
| return [[path, obj1, obj2]]; | |
| } | |
| const diffs: ReturnType<typeof deepDiffR> = []; | |
| for (const prop in obj1) { | |
| diffs.push(...deepDiffR(obj1[prop], obj2[prop], [...path, prop])); | |
| } | |
| return diffs; | |
| } | |
| return [[path, obj1, obj2]]; | |
| } | |
| /** | |
| * @internal | |
| */ | |
| function isObject( | |
| obj: any | |
| ): obj is { [key: string]: any; [keyN: number]: any } { | |
| return typeof obj === "object" && obj != null; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment