import { TupleKeys } from './Types.js'; /** * Comparators compare two objects. * * @typeParam the object type supported by this function * @param a first object to compare * @param b second object to compare * @returns Returns `< 0` if `a < b`, `> 0` if `a > b` and `0` if `a == b`. */ type Comparator = (a: T, b: T) => number; /** * Compares values using the builtin operators `<` and `>` and '==='. * * This function is not specified for null, undefined, functions or objects. * If such things are compared and they are not equal, then the first argument is always treated as smaller. * e.g. `DEFAULT_COMPARE({}, undefined) === DEFAULT_COMPARE(undefined, {}) === -1` * */ declare const DEFAULT_COMPARE: (a: any, b: any) => number; /** * A comparison function suitable for sorting heterogenous primitive values to a predictable order. * Values are ordered by type first and then compared by value. * Note that `null` is treated as its own type for the purpose of this function, sorting directly after `undefined`. * * Symbols, objects and functions are grouped but have no useful ordering between them. */ declare const TYPE_BASED_COMPARE: (a: any, b: any) => number; /** * Compares strings while treating uppercase and lowercase characters as equal. * This methods will throw an error if the objects are no strings. * */ declare const IGNORE_CASE: (a: any, b: any) => number; /** * Factory to create a comparator to compare strings using localCompare function. * @param locale locale, e.g. `en` or `de`. * @param ignoreCase `true`, if strings should be compared ignoring case, otherwise `false`. * @param numeric `true`, try to interpret the string as number * @returns comparator for strings */ declare function createStringComparator(locale?: string, ignoreCase?: boolean, numeric?: boolean): Comparator; /** * Factory to create a string comparator which compares strings respecting numeric parts of the given strings. * The comparator splits the input into string and numeric parts to compare them separately. * @example * ```ts * const comparator = createStringWithNumberPartsComparator(); * const values = ["a1", "a10", "a2", "b1", "a20", "a3"]; * values.sort(comparator); * assert.deepStrictEqual(["a1", "a2", "a3", "a10", "a20", "b1"], values); * ``` * @param locale locale, e.g. `en` or `de`. * @param ignoreCase `true`, if strings should be compared ignoring case, otherwise `false`. * @returns comparator for comparing strings with numeric parts */ declare function createStringWithNumberPartsComparator(locale?: string, ignoreCase?: boolean): Comparator; /** * An interface implemented by objects with custom comparison logic. * Used in conjunction with {@link BY_COMPARE_TO}. */ interface Comparable { /** * Compares `this` to `other`. * Returns `< 0` if `this < other`, `> 0` if `this > other` and `0` if `this == other`. */ compareTo(other: T): number; } /** * Compares objects using the compareTo function provided in the first object. * If the 'compareTo' function is not available then it falls back to the DEFAULT_COMPARE. * @example _Usage with a class_ * ``` * import { BY_COMPARE_TO, DEFAULT_COMPARE } from "apprt-core/comparators" * * class Sample { * constructor({ id, msg = "" }) { * this.id = id; * this.msg = msg; * } * compareTo(other) { * return DEFAULT_COMPARE(this.id, other?.id); * } * } * * const lotOfSamples = [new Sample({ id: "C" }), new Sample({ id: "F" }), new Sample({ id: "B" })]; * lotOfSamples.sort(BY_COMPARE_TO); * assert.deepEqual(["B", "C", "F"], lotOfSamples.map((s) => s.id)); * ``` */ declare const BY_COMPARE_TO: (a: Partial>, b: any) => number; /** * Specifies advanced sorting behavior for a given field. */ interface FieldSpecObject { /** The field name to sort by. Numbers can be used for array indices. */ field?: FieldName; /** To reverse the sort order (default: false). */ reverse?: boolean; /** Custom comparator function used for values of this field (optional). */ compare?: Comparator; /** * Custom value picker, used to lookup the field in the target instance. * If defined, the field name can be skipped. * Allows default values to be provided. * @param instance object with field. * @returns value to compare. */ valuePicker?: (instance: ObjectType) => FieldType | undefined; } type AllFieldSpecObjects = { [P in AllowedKeys]: FieldSpecObject; }[AllowedKeys]; /** * This type describes all valid field specs for the given object type. * Legal field specs are either a valid field name (strings for objects, or numbers for tuples) * or an object that looks like a FieldSpecObject (again, with a valid field name). */ type FieldSpec = ObjectType extends any[] ? // Integers and numeric strings as keys for tuples TupleKeys | AllFieldSpecObjects> : // "normal" keys for records keyof ObjectType | AllFieldSpecObjects; /** * Creates a new comparator function that compares the fields of its input arguments using the given specification. * The function can then be used, for example, in calls to _Array.sort()_. * * @example _Sort by age, then by name_ * ```ts * const data = [ * { name: "B", age: 21 }, * { name: "A", age: 21 }, * { name: "C", age: 20 } * ]; * // Orders by age, or if ages are equal, by name. * data.sort(compareFields("age", "name")); * ``` * * @example _Reverse sort order for a single field_ * ```ts * const data = [ * { name: "B", age: 21 }, * { name: "A", age: 21 }, * { name: "C", age: 20 } * ]; * data.sort(compareFields({ field: "age", reverse: true }, "name")); * ``` * * @example _Compare array items using indices as field "names"_ * ```ts * const data = [ * [1, 2], * [1, 3], * [2, 3], * ]; * // Orders by array item at index 1, or by index 0 if the other values are equal. * data.sort(compareFields(1, 0)); * ``` * * @example _Compare field values with a custom comparator_ * ```ts * const compare = (a, b) => b - a; // Some custom comparison logic * const data = [ * { value: 3 }, * { value: 4 }, * ]; * // Compares value using the custom comparison function * data.sort(compareFields({ field: "value", compare: compare })); * ``` * * @example _Compare field values with a custom value picker_ * ```ts * const valuePicker = (a) => a.value ?? 0; // Some custom value lookup logic, e.g. default values * const data = [ * { value: 3 }, * { value: 4 }, * ]; * // Compares value using the custom comparison function * data.sort(compareFields({ valuePicker })); * ``` * * @param fields * A list of fields that specify the object comparison. * This can be a direct field name or an object specifier for advanced configuration. * Multiple field names or objects are also supported, in which case the new comparator will create a * [lexicographic order](https://en.wikipedia.org/wiki/Lexicographic_order) based on these fields. * * A field name is considered to be a string for member attributes, or a number to indicate a particular * index of an array within the array to be sorted. * * The default comparison function compares fields using the builtin `<` and `>` operators, but a custom * compare function can be specified when using the object notation. * * The order returned by the comparator is _ascending_ by default. * * @returns the new comparator function. * */ declare function compareFields(...fields: FieldSpec[]): Comparator; export { BY_COMPARE_TO, DEFAULT_COMPARE, IGNORE_CASE, TYPE_BASED_COMPARE, compareFields, createStringComparator, createStringWithNumberPartsComparator }; export type { Comparable, Comparator, FieldSpecObject };