Quiero crear una función que tome como entrada una matriz de Objetos, un Objeto y una clave y devuelva una Matriz de Objetos que contenga el nuevo Objeto en la posición 0 si es un Objeto nuevo o en la misma posición si no es un nuevo una. La clave se usa para comparar los Objetos y puede ser solo una cadena o un número.
Escribí este pero es obligatorio tener una propiedad de identificación dentro de los Objetos.
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; }
Considere este ejemplo:
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] }
El ejemplo anterior reducirá un poco la complejidad. la operación unshift
es costosa. Es por eso que creé una nueva estructura de datos {exists: boolean, arr:Obj[]}
.
También he devuelto una nueva matriz en lugar de la mutación de la matriz existente
Puedes escribir tu función así:
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; };