const isSet = (x: any) => x != null; // works for [null, undefined], [ false, 0, Nan ] are true
const isNumber = (x: any) => typeof x === "number";
const isString = (x: any) => typeof x === "string";
const isIterable = (value: any) => Symbol.iterator in Object(value);
const stringComparer = (locales?: any, options?: any) => {
if (!locales) locales = "en";
if (!options) options = { numeric: true, sensitivity: "base" };
const collator = new Intl.Collator(locales, options);
return (a: string, b: string) => collator.compare(a, b);
};
const comparer = stringComparer();
function compare(a: any, b: any, reverse: boolean): number {
const [x, y] = reverse ? [b, a] : [a, b];
if (!isSet(x) && !isSet(y)) return 0;
if (!isSet(x) && isSet(y)) return -1;
if (!isSet(y) && isSet(x)) return 1;
if (isNumber(x) && isNumber(y)) return x - y;
if (isString(x) && isString(y)) return comparer(x, y);
if (isIterable(x) && isIterable(y)) {
for (const d of Array.from(zipIterables(x, y))) {
const c = compare(d[0], d[1], reverse);
if (c !== 0) return c;
}
return 0;
}
return comparer(String(x), String(y));
}
export function orderBy<T>(array: T[], fn: (x: T) => any, reverse?: boolean) {
const result = Array.from(array);
result.sort((a, b) => compare(fn(a), fn(b), reverse || false));
return result;
};
// Example use:
// Sort events first on 'start' date property, when start equals compare the 'end' property
orderBy(events, (e) => [e.start, e.end]);
532520cookie-checkTypescript / javascript OrderBy