Skip to content

Typescript return type of sort/sortBy on non-Ordered Collections isn't accurate #2012

Closed
@cypherfunc

Description

@cypherfunc

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:

* 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:

immutable-js/src/Map.js

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));
}

immutable-js/src/Set.js

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>:

sort(comparator?: Comparator<V>): this;

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting-responseAwaiting response from creator. Can't fix without it.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy