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.
CodePudding user response:
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"
}