export interface DifferenceResult { toAdd: ReadonlySet; toRemove: ReadonlySet; } export function getDifference(from: Iterable, to: Iterable): DifferenceResult { const fromSet = new Set(from); const toSet = new Set(to); return { toAdd: findNotIn(toSet, fromSet), toRemove: findNotIn(fromSet, toSet), }; } /** * Find all the values in a that are not in b * @param a * @param b */ function findNotIn(a: ReadonlySet, b: ReadonlySet): ReadonlySet { const result = new Set(); for (const value of a) { if (!b.has(value)) { result.add(value); } } return result; } export function toArray(item: T | readonly T[]): T[] { return Array.isArray(item) ? item : ([item] as T[]); }