Skip to content

Commit 78c8c4e

Browse files
committed
feat(core): Allow comparator to return a number
1 parent 2df18b2 commit 78c8c4e

5 files changed

Lines changed: 42 additions & 6 deletions

File tree

projects/ngqp/core/src/lib/serializers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isMissing } from './util';
1+
import { areEqualUsing, isMissing } from './util';
22
import { Comparator, ParamDeserializer, ParamSerializer } from './types';
33

44
/**
@@ -13,7 +13,7 @@ import { Comparator, ParamDeserializer, ParamSerializer } from './types';
1313
* @param compareWith The comparator function to compare two values.
1414
*/
1515
export function createEmptyOnSerializer<T>(serializer: ParamSerializer<T>, emptyOn: T, compareWith: Comparator<T>): ParamSerializer<T> {
16-
return model => compareWith(model, emptyOn) ? null : serializer(model);
16+
return model => areEqualUsing(model, emptyOn, compareWith) ? null : serializer(model);
1717
}
1818

1919
/**

projects/ngqp/core/src/lib/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ export type OnChangeFunction<T> = (value: T | null) => void;
2525

2626
/**
2727
* A function which compares two values of the same type to determine
28-
* if they are equal.
28+
* if they are equal. To support traditional comparator functions, you
29+
* can also return a number where "0" means equality.
2930
*
3031
* @param a First value to compare.
3132
* @param b Second value to compare.
32-
* @returns `true` if and only if `a` and `b` should be considered equal.
33+
* @returns `true` or `0` if and only if `a` and `b` should be considered equal.
3334
*/
34-
export type Comparator<T> = (a: T | undefined | null, b: T | undefined | null) => boolean;
35+
export type Comparator<T> = (a: T | undefined | null, b: T | undefined | null) => boolean | number;
3536

3637
/**
3738
* Unpacks an array type.

projects/ngqp/core/src/lib/util.spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { isFunction, isMissing, LOOSE_IDENTITY_COMPARATOR, wrapTryCatch } from './util';
1+
import { areEqualUsing, isFunction, isMissing, LOOSE_IDENTITY_COMPARATOR, wrapTryCatch } from './util';
2+
import { Comparator } from './types';
23

34
describe(isMissing.name, () => {
45
it('returns true for undefined', () => expect(isMissing(undefined)).toBe(true));
@@ -73,4 +74,24 @@ describe(LOOSE_IDENTITY_COMPARATOR.name, () => {
7374
it(`returns false for ${a} / ${b}`,
7475
() => expect(LOOSE_IDENTITY_COMPARATOR(a, b)).toBe(false));
7576
});
77+
});
78+
79+
describe(areEqualUsing.name, () => {
80+
const numericComparator: Comparator<number> = (a, b) => b - a;
81+
82+
it('returns true if a boolean comparator returns true', () =>
83+
expect(areEqualUsing(42, 42, LOOSE_IDENTITY_COMPARATOR)).toBe(true)
84+
);
85+
86+
it('returns false if a boolean comparator returns false', () =>
87+
expect(areEqualUsing(42, 1337, LOOSE_IDENTITY_COMPARATOR)).toBe(false)
88+
);
89+
90+
it('returns true if a numeric comparator returns 0', () =>
91+
expect(areEqualUsing(42, 42, numericComparator)).toBe(true)
92+
);
93+
94+
it('returns false if a numeric comparator returns a non-zero value', () =>
95+
expect(areEqualUsing(42, 1337, numericComparator)).toBe(false)
96+
);
7697
});

projects/ngqp/core/src/lib/util.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Comparator } from './types';
2+
13
/** @internal */
24
// tslint:disable-next-line:triple-equals
35
export const LOOSE_IDENTITY_COMPARATOR = <T>(a: T, b: T) => a == b;
@@ -22,4 +24,14 @@ export function wrapTryCatch<T extends Function>(fn: T, msg: string): T {
2224
return null;
2325
}
2426
};
27+
}
28+
29+
/** @internal */
30+
export function areEqualUsing<T>(first: T, second: T, comparator: Comparator<T>): boolean {
31+
const comparison = comparator(first, second);
32+
if (typeof comparison === 'boolean') {
33+
return comparison;
34+
}
35+
36+
return comparison === 0;
2537
}

projects/ngqp/core/src/test/util.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/** See https://github.com/angular/angular/issues/25837 */
2+
import { Comparator } from '../lib/types';
3+
24
export function setupNavigationWarnStub() {
35
const warn = console.warn;
46

0 commit comments

Comments
 (0)