Skip to content

Instantly share code, notes, and snippets.

@touhidrahman
Last active October 11, 2018 22:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save touhidrahman/b08e1d37036cc564c980bf4a01b57133 to your computer and use it in GitHub Desktop.
Save touhidrahman/b08e1d37036cc564c980bf4a01b57133 to your computer and use it in GitHub Desktop.
Compare two similar/identical javascript objects for differences. Returns the changed properties filled with updated value, and unchanged fields with null.
export class ObjectDiff {
isObject(obj: Object): boolean {
return typeof obj === 'object' && !Array.isArray(obj)
}
isArray(obj: Object): boolean {
return Array.isArray(obj)
}
isPrimitive(obj: Object): boolean {
return typeof obj !== 'object'
}
/**
* Checks a property of an object value of which is of primitive type (string, number, boolean)
* for changes and returns the changed value, otherwise null
*/
diffPrimitive(path: string, beforeObj: Object, afterObj: Object): any | null {
if (!beforeObj || !afterObj) return null
if (beforeObj[path] !== afterObj[path])
return afterObj[path]
return null
}
/**
* Checks two objects for differences and returns the changed properties filled
* with updated value, and unchanged fields with null
*/
diffObject(beforeObj: Object, afterObj: Object): any {
if (!beforeObj || !afterObj) return
const result = {}
Object.keys(beforeObj).forEach(key => {
if (this.isPrimitive(beforeObj[key]))
result[key] = this.diffPrimitive(key, beforeObj, afterObj)
if (this.isObject(beforeObj[key]))
result[key] = this.diffObject(beforeObj[key], afterObj[key])
if (this.isArray(beforeObj[key]))
result[key] = this.diffArray(beforeObj[key], afterObj[key])
})
return result
}
/**
* Checks two arrays for differences and returns the changed elements filled
* with updated value, and unchanged elements with null. The elements can be
* object or array as well.
*/
diffArray(beforeArray: Array<any>, afterArray: Array<any>): Array<any> {
if (!beforeArray || !afterArray) return
const result = [ ...beforeArray ]
for(let i = 0; i < beforeArray.length; i++) {
if (this.isPrimitive(beforeArray[i]))
beforeArray[i] === afterArray[i]
? result[i] = null
: result[i] = afterArray[i]
if (this.isObject(beforeArray[i]))
result[i] = this.diffObject(beforeArray[i], afterArray[i])
if (this.isArray(beforeArray[i]))
result[i] = this.diffArray(beforeArray[i], afterArray[i])
}
return result
}
}
/*******************
* Tests *
*******************/
let main = new ObjectDiff()
const a = {
test: "test",
same: "same",
nested: {
x: "x"
},
arr: [ 1, 2, 7],
arrObjs: [
{ y: "y"},
{ z: "z"}
]
}
const b = {
test: "test1",
same: "same",
nested: {
x: "x"
},
arr: [ 1, 2, 3],
arrObjs: [
{ y: "y"},
{ z: "a"}
]
}
const res = main.diffObject(a, b)
console.log(res)
/**
* Should print:
* {
* test: 'test1',
* same: null,
* nested: { x: null },
* arr: [ null, null, 3 ],
* arrObjs: [ { y: null }, { z: 'a' } ]
* }
*
*
* Run file
*
* `tsc objectdiff.ts && node objectdiff.js`
*/
@asanfilov
Copy link

asanfilov commented Oct 4, 2018

Would you replace console.log with Assert methods? For example, using Mocha.js and Chai.js
https://journal.artfuldev.com/unit-testing-node-applications-with-typescript-using-mocha-and-chai-384ef05f32b2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment