Implement intersectionWith(...arrays, comparator) — return the elements of the first array that have a match in every other array, where "match" is decided by a comparator(a, b) you pass in as the last argument. This mirrors Lodash's _.intersectionWith. The twist that makes it interesting: instead of comparing by a value or a derived key, you compare with an arbitrary two-argument predicate — so you can intersect objects by a field, numbers by a tolerance, or anything else equality can't express directly.
// ...arrays: T[][] — one or more arrays to intersect.
// comparator: (a: T, b: T) => boolean — the LAST argument; returns true when
// two elements should count as equal.
// returns: T[]
// The elements of the FIRST array (originals, in order, deduped) that have
// at least one comparator-match in EVERY other array.
function intersectionWith(...arrays, comparator): T[];
// Object equality by a field: keep first-array objects whose id appears in the other.
const cmp = (a, b) => a.id === b.id;
intersectionWith([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], cmp);
// → [{ id: 2 }]
// Numeric tolerance: 2.0 is "within 0.5" of 2.4, but 1.0 has no partner.
const close = (a, b) => Math.abs(a - b) < 0.5;
intersectionWith([1.0, 2.0], [2.4, 9], close);
// → [2.0]
// Three arrays: an element must match in ALL of them. Only 2 survives.
const eq = (a, b) => a === b;
intersectionWith([1, 2, 3], [1, 2], [2, 3], eq);
// → [2]
intersectionWith(a, b, c, cmp), you intersect a, b, and c; cmp decides equality.{ id: 2 } from the first array matches { id: 2 } from another, you return the first array's object, not the other one — they may differ in their other fields.comparator(firstEl, otherEl). The first array's element is always the first argument — it matters for asymmetric comparators.[]. Don't mutate the inputs.