-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
What happened
When calling .sort()
or .sortBy()
on non-"Ordered" Collections like Maps and Sets, the return type is the same as the original Collection, when it actually returns the "Ordered" version.
According to the docs:
immutable-js/type-definitions/immutable.d.ts
Lines 4570 to 4582 in 0c2d021
* When sorting collections which have no defined order, their ordered | |
* equivalents will be returned. e.g. `map.sort()` returns OrderedMap. | |
* | |
* <!-- runkit:activate --> | |
* ```js | |
* const { Map } = require('immutable') | |
* Map({ "c": 3, "a": 1, "b": 2 }).sort((a, b) => { | |
* if (a < b) { return -1; } | |
* if (a > b) { return 1; } | |
* if (a === b) { return 0; } | |
* }); | |
* // OrderedMap { "a": 1, "b": 2, "c": 3 } | |
* ``` |
This matches the implementations:
Lines 112 to 120 in 0c2d021
sort(comparator) { | |
// Late binding | |
return OrderedMap(sortFactory(this, comparator)); | |
} | |
sortBy(mapper, comparator) { | |
// Late binding | |
return OrderedMap(sortFactory(this, comparator, mapper)); | |
} |
Lines 153 to 161 in 0c2d021
sort(comparator) { | |
// Late binding | |
return OrderedSet(sortFactory(this, comparator)); | |
} | |
sortBy(mapper, comparator) { | |
// Late binding | |
return OrderedSet(sortFactory(this, comparator, mapper)); | |
} |
However the TS types just use the inherited definitions from interface Collection<K, V>
:
immutable-js/type-definitions/immutable.d.ts
Line 4589 in 0c2d021
sort(comparator?: Comparator<V>): this; |
immutable-js/type-definitions/immutable.d.ts
Lines 4612 to 4615 in 0c2d021
sortBy<C>( | |
comparatorValueMapper: (value: V, key: K, iter: this) => C, | |
comparator?: Comparator<C> | |
): this; |
It's possible to monkey-patch the Map and Set interfaces like this:
declare module "immutable" {
export interface Map<K, V> {
sort(comparator?: Comparator<V>): OrderedMap<K, V>;
sortBy<C>(
comparatorValueMapper: (value: V, key: K, iter: this) => C,
comparator?: (valueA: C, valueB: C) => number
): OrderedMap<K, V>;
}
export interface Set<T> {
sort(comparator?: Comparator<T>): OrderedSet<T>;
sortBy<C>(
comparatorValueMapper: (value: T, key: T, iter: this) => C,
comparator?: (valueA: C, valueB: C) => number
): OrderedSet<T>;
}
}
However, I don't know enough to recommend that as the real fix. This issue probably also affects some other types besides just Map and Set, and it might be better to add the accurate definitions on one of the abstract types, or some other interface. 🤷
How to reproduce
Call .sort()
or .sortBy()
on a Map or Set and look at the returned type.