Created
May 23, 2021 17:29
-
-
Save RazerMoon/53f5adf4eeded7d439eb2ba480bfd1c5 to your computer and use it in GitHub Desktop.
Difference between two objects
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
// ? Taken from https://stackoverflow.com/questions/8572826/generic-deep-diff-between-two-objects but changed to only return changes. | |
// ! DO NOT USE IN PRODUCTION, UNTESTED AND LIKELY UNSTABLE | |
const deepDiffMapper = (function () { | |
return { | |
VALUE_CREATED: "created", | |
VALUE_UPDATED: "updated", | |
VALUE_DELETED: "deleted", | |
VALUE_UNCHANGED: "unchanged", | |
map: function (obj1, obj2) { | |
if (this.isFunction(obj1) || this.isFunction(obj2)) { | |
throw "Invalid argument. Function given, object expected."; | |
} | |
if (this.isValue(obj1) || this.isValue(obj2)) { | |
const type = this.compareValues(obj1, obj2); | |
if (type !== this.VALUE_UPDATED) { | |
return null; | |
} | |
return obj1 === undefined | |
? obj2 | |
: obj1; | |
} | |
const diff = {}; | |
for (const key in obj1) { | |
if (this.isFunction(obj1[key])) { | |
continue; | |
} | |
let value2 = undefined; | |
if (obj2[key] !== undefined) { | |
value2 = obj2[key]; | |
} | |
const change = this.map(obj1[key], value2); | |
if (change === null) { | |
continue; | |
} | |
diff[key] = change; | |
} | |
for (const key in obj2) { | |
if (this.isFunction(obj2[key]) || | |
diff[key] !== undefined) { | |
continue; | |
} | |
const change = this.map(undefined, obj2[key]); | |
if (change === null) { | |
continue; | |
} | |
diff[key] = change; | |
} | |
return diff; | |
}, | |
compareValues: function (value1, value2) { | |
if (value1 === value2) { | |
return this.VALUE_UNCHANGED; | |
} | |
if (this.isDate(value1) && | |
this.isDate(value2) && | |
value1.getTime() === value2.getTime()) { | |
return this.VALUE_UNCHANGED; | |
} | |
if (value1 === undefined) { | |
return this.VALUE_CREATED; | |
} | |
if (value2 === undefined) { | |
return this.VALUE_DELETED; | |
} | |
return this.VALUE_UPDATED; | |
}, | |
isFunction: function (x) { | |
return Object.prototype.toString.call(x) === "[object Function]"; | |
}, | |
isArray: function (x) { | |
return Object.prototype.toString.call(x) === "[object Array]"; | |
}, | |
isDate: function (x) { | |
return Object.prototype.toString.call(x) === "[object Date]"; | |
}, | |
isObject: function (x) { | |
return Object.prototype.toString.call(x) === "[object Object]"; | |
}, | |
isValue: function (x) { | |
return !this.isObject(x) && !this.isArray(x); | |
}, | |
}; | |
})(); | |
export default deepDiffMapper; |
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
type UnknownObject = { | |
[k: string]: unknown; | |
}; | |
// ? Taken from https://stackoverflow.com/questions/8572826/generic-deep-diff-between-two-objects but changed to only return changes. | |
// ! DO NOT USE IN PRODUCTION, UNTESTED AND LIKELY UNSTABLE | |
const deepDiffMapper = (function () { | |
return { | |
VALUE_CREATED: "created", | |
VALUE_UPDATED: "updated", | |
VALUE_DELETED: "deleted", | |
VALUE_UNCHANGED: "unchanged", | |
map: function (obj1: unknown, obj2: unknown): UnknownObject | null { | |
if (this.isFunction(obj1) || this.isFunction(obj2)) { | |
throw "Invalid argument. Function given, object expected."; | |
} | |
if (this.isValue(obj1) || this.isValue(obj2)) { | |
const type = this.compareValues(obj1, obj2); | |
if (type !== this.VALUE_UPDATED) { | |
return null; | |
} | |
return obj1 === undefined | |
? (obj2 as UnknownObject) | |
: (obj1 as UnknownObject); | |
} | |
const diff: UnknownObject = {}; | |
for (const key in obj1 as UnknownObject) { | |
if (this.isFunction((obj1 as UnknownObject)[key])) { | |
continue; | |
} | |
let value2 = undefined; | |
if ((obj2 as UnknownObject)[key] !== undefined) { | |
value2 = (obj2 as UnknownObject)[key]; | |
} | |
const change = this.map((obj1 as UnknownObject)[key], value2); | |
if (change === null) { | |
continue; | |
} | |
diff[key] = change; | |
} | |
for (const key in obj2 as UnknownObject) { | |
if ( | |
this.isFunction((obj2 as UnknownObject)[key]) || | |
diff[key] !== undefined | |
) { | |
continue; | |
} | |
const change = this.map(undefined, (obj2 as UnknownObject)[key]); | |
if (change === null) { | |
continue; | |
} | |
diff[key] = change; | |
} | |
return diff; | |
}, | |
compareValues: function (value1: unknown, value2: unknown) { | |
if (value1 === value2) { | |
return this.VALUE_UNCHANGED; | |
} | |
if ( | |
this.isDate(value1) && | |
this.isDate(value2) && | |
(value1 as Date).getTime() === (value2 as Date).getTime() | |
) { | |
return this.VALUE_UNCHANGED; | |
} | |
if (value1 === undefined) { | |
return this.VALUE_CREATED; | |
} | |
if (value2 === undefined) { | |
return this.VALUE_DELETED; | |
} | |
return this.VALUE_UPDATED; | |
}, | |
isFunction: function (x: unknown) { | |
return Object.prototype.toString.call(x) === "[object Function]"; | |
}, | |
isArray: function (x: unknown) { | |
return Object.prototype.toString.call(x) === "[object Array]"; | |
}, | |
isDate: function (x: unknown) { | |
return Object.prototype.toString.call(x) === "[object Date]"; | |
}, | |
isObject: function (x: unknown) { | |
return Object.prototype.toString.call(x) === "[object Object]"; | |
}, | |
isValue: function (x: unknown) { | |
return !this.isObject(x) && !this.isArray(x); | |
}, | |
}; | |
})(); | |
export default deepDiffMapper; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment