I'm trying to compare two objects of the same type. What I want to achieve at the end, is a new object with only the properties that are different.
For example:
type A = {
id: string;
col: number;
enabled: true;
obj: {
b: number;
}
}
const a: A = {
id: "ddd",
col: 4,
enabled: true,
obj: {
b: 4
}
}
const b: A = {
id: "dde",
col: 4,
enabled: true,
obj: {
b: 3
}
}
const c = () => Object.values(a).reduce((bef, aft, i) => {
const valuesB = Object.values(b);
const keyB = Object.keys(b)[i];
return valuesB[i] === aft ? { ...bef } : { keyB: valuesB[i], ...bef }
}, {})
With my logic above I was able to get a new object like:
{
"keyB": "dde"
}
It got the value right but the key wrong and also ignored the fact that the nested object property has different values. I'm a bit stuck and out of ideas.
Any help would be extremely appreciated.
About the incorrect key, you'd just have to add brackets around keyB
to use the value of the variable as key: { [keyB]: valueB, ...bef }
About the missing nested object, that's a bit more complicated but here's a solution:
const diff = <T>(obj1: T, obj2: T): Partial<T> =>
Object.values(obj1).reduce((bef, aft, i) => {
const valueB = Object.values(obj2)[i];
const keyB = Object.keys(obj2)[i];
if (valueB instanceof Object) {
const delta = diff(valueB, aft);
return Object.keys(delta).length > 0 ? { [keyB]: diff(valueB, aft), ...bef } : bef;
}
return valueB === aft ? bef : { [keyB]: valueB, ...bef };
}, {});
const c = (): Partial<A> => diff(a, b);
You have to check each field of the nested object separately. That's what the recursion is for.
I also added typings to the functions. Partial<A>
is a copy of A
but makes all fields optional.
The result is:
{
"obj": {
"b": 4
},
"id": "dde"
}