Skip to content

Instantly share code, notes, and snippets.

@tusharmath
Created August 16, 2018 01:00
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 tusharmath/64ddd63174541f6a4fb208aa177626a7 to your computer and use it in GitHub Desktop.
Save tusharmath/64ddd63174541f6a4fb208aa177626a7 to your computer and use it in GitHub Desktop.
Finds diff between objects
type Change<T> = {
path: Array<string>
right: T
left: T
}
function isPrimitive(value: any): boolean {
const type = typeof value
return ['number', 'date', 'boolean', 'string'].indexOf(type) > -1
}
function change<T>(path: Array<string>, a: T, b: T): Change<T> {
return {
path,
left: a,
right: b
}
}
function arrToDict<T>(t: Array<T>): { [key: number]: T } {
const obj: any = {}
for (let i = 0; i < t.length; i++) obj[i] = t[i]
return obj
}
function diffAB<T extends any>(a: T, b: T, path: string[]): Array<Change<T>> {
let changes: Array<Change<any>> = []
for (let i in a) {
if (a.hasOwnProperty(i)) {
if (b.hasOwnProperty(i)) {
changes = changes.concat(diff(a[i], b[i], [...path, i]))
} else {
changes = changes.concat([change([...path, i], a[i], b[i])])
}
}
}
for (let i in b) {
if (b.hasOwnProperty(i)) {
if (!a.hasOwnProperty(i)) {
changes = changes.concat([change([...path, i], a[i], b[i])])
}
}
}
return changes
}
function diff(a: any, b: any, path: Array<string> = []): Array<Change<any>> {
if (a === b) return []
// primitive check
if (
(isPrimitive(a) && !isPrimitive(b)) ||
(!isPrimitive(a) && isPrimitive(b)) ||
(isPrimitive(a) && isPrimitive(b) && a !== b)
)
return [change(path, a, b)]
if (Array.isArray(a) && Array.isArray(b))
return diffAB(arrToDict(a), arrToDict(b), path)
return diffAB(a, b, path)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment