export interface Identifiable { id: number | string } export interface UniqueList { elements: Record } export function createUniqueList(): UniqueList { return { elements: {} } } export function uniqueListUpdate( list: UniqueList, dataList: T[], addCallback?: (it: T) => void, removeCallback?: (it: T) => void, updateCallback?: (oldElement: T, newElement: T) => void ): void { const elementsToAdd = dataList.filter((it) => list.elements[String(it.id)] === undefined) const elementsToRemove: T[] = [] for (const id of Object.keys(list.elements)) { if (dataList.find((up) => String(up.id) === id) === undefined) { const el = list.elements[id] if (el) elementsToRemove.push(el) } } if (removeCallback) { elementsToRemove.forEach((it) => removeCallback(it)) } if (updateCallback) { dataList.forEach((newElement) => { const oldElement = list.elements[String(newElement.id)] if (oldElement) { updateCallback(oldElement, newElement) } }) } if (addCallback) { elementsToAdd.forEach((it) => addCallback(it)) } const toRemove = new Set(elementsToRemove.map((it) => String(it.id))) list.elements = Object.fromEntries( Object.entries(list.elements).filter(([id]) => !toRemove.has(id)) ) as Record elementsToAdd.forEach((it) => (list.elements[String(it.id)] = it)) } export function uniqueListGetElements(list: UniqueList): T[] { return Object.values(list.elements) } export function uniqueListById(list: UniqueList, id: number | string): T | undefined { return list.elements[String(id)] }