multiKeyComparatorWithNullsLast

JavaScript
// Builds a comparator for records with ordered keys and nullish values last.
const isNullish = (value) => value === null || value === undefined;

export function multiKeyComparator(keys, collator = new Intl.Collator()) {
  return (left, right) => {
    for (const spec of keys) {
      const key = typeof spec === 'string' ? spec : spec.key;
      const direction = typeof spec === 'string' || spec.direction !== 'desc' ? 1 : -1;
      const a = left?.[key];
      const b = right?.[key];
      if (isNullish(a) && isNullish(b)) continue;
      if (isNullish(a)) return 1; // nullish always sorts last, even descending
      if (isNullish(b)) return -1;
      let result = 0;
      if (typeof a === 'number' && typeof b === 'number') result = a - b;
      else if (a instanceof Date && b instanceof Date) result = a.getTime() - b.getTime();
      else result = collator.compare(String(a), String(b));
      if (result !== 0) return result * direction;
    }
    return 0;
  };
}