I want to create a function that takes in input an array of Objects, an Object, and a key and returns an Array of Objects that contains the new Object on position 0 if it's a new Object or at the same position if it's not a new one. The key is used to compare the Objects and can be only a string or a number.
I wrote this one but it's mandatory to have an id property inside the Objects.
export function addOrReplaceById<T extends Array<{ id: string }>>(
arrayOfObjects: T,
newObject: { id: string }
): T {
const index = arrayOfObjects.findIndex((object) => object.id === newObject.id);
if (index === -1) {
arrayOfObjects.unshift(newObject);
} else {
arrayOfObjects[index] = newObject;
}
return arrayOfObjects;
}
CodePudding user response:
Consider this example:
export function addOrReplaceById<
Obj extends { id: string },
Arr extends Array<Obj>
>(
arrayOfObjects: [...Arr],
newObject: Obj
) {
const data = arrayOfObjects
.reduce<{ exists: boolean, arr: Obj[] }>(
(acc, obj) =>
obj.id === newObject.id ? {
...acc,
exists: true,
arr: [...acc.arr, newObject]
} : acc, {
exists: false,
arr: []
});
return data.exists ? data.arr : [newObject, ...data.arr]
}
Above example will reduce a complexity a bit. unshift
operation is expensive. That's why I created new data structure {exists: boolean, arr:Obj[]}
.
Also I have returned new array instead of mutation of existing array
CodePudding user response:
You can write your function like this:
export function addOrReplaceByKey<T extends {[x: string]: any}>(
arrayOfObjects: T[],
newObject: T,
key: keyof T,
): T[] {
const index = arrayOfObjects.findIndex((object) => object[key] === newObject[key]);
if (index === -1) {
arrayOfObjects.unshift(newObject);
} else {
arrayOfObjects[index] = newObject;
}
return arrayOfObjects;
};