Skip to content

Instantly share code, notes, and snippets.

@tanishqmanuja
Created May 23, 2025 08:41
Show Gist options
  • Save tanishqmanuja/7691d9e4e32bb4611e1af9c0febd50ed to your computer and use it in GitHub Desktop.
Save tanishqmanuja/7691d9e4e32bb4611e1af9c0febd50ed to your computer and use it in GitHub Desktop.
Utility to Combine Comparators for easy sorting!
/* Helper Types */
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (
x: infer I
) => void
? I
: never;
/* Comparator */
export type Comparator<T> = (a: T, b: T) => number;
export type CombinedComparator<T extends Comparator<unknown>[]> = Comparator<
UnionToIntersection<Parameters<T[number]>[0]>
>;
export const Comparator = {
combine<CInputs extends Comparator<any>[]>(
...comparators: CInputs
): CombinedComparator<CInputs> {
return (a, b) =>
comparators.reduce((result, comparator) => {
return result !== 0
? result
: (comparator as CombinedComparator<CInputs>)(a, b);
}, 0);
},
from<T, K extends string | number | boolean>(
selector: (x: T) => K,
order: "asc" | "desc" = "asc"
): Comparator<T> {
return (a, b) => {
const aKey = selector(a);
const bKey = selector(b);
let result: number;
if (typeof aKey === "string" && typeof bKey === "string") {
result = aKey.localeCompare(bKey);
} else {
result = aKey < bKey ? -1 : aKey > bKey ? 1 : 0;
}
return order === "asc" ? result : -result;
};
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment