-1

I'm trying to build a sort function that should be able to work with and without promises indistictevly.

The function fingerprint should be something like this:

function sort<T>(list: T[], fn: (item: T) => string | number): T[];
function sort<T>(list: Promise<T[]>, fn: (item: T) => string | number): Promise<T[]>;

So the idea is that I can use it regardless if list is or not a promise while the return type should match the input type.

I've done this kind of constructions with other types (like a map function for both arrays and objects) but promises present an additional challenge as I would need to declare the method as async in order to plus, doing so, it forces me to always return a promise.

How can I do this? Is this even possible?

carlosV2
  • 1,167
  • 6
  • 15
  • How on earth did you find the solution right at the time you posted it? I mean seconds by seconds – Ryan Le Aug 26 '21 at 11:44
  • After I got the question written down I started to think on why Typescript forces me to use Promise when declaring the function as `async` so I started playing with the code (still haven't submitted the question). Eventually I figured it out that without `async`, you can return whatever you want being a promise a valid return too. I was about to remove the question but then I thought somebody else would benefit from it so I posted the answer. If it is not that useful, I can remove it. I certainly took me a lot of time to figure it out. – carlosV2 Aug 26 '21 at 14:55

1 Answers1

0

Ok, just figured it out myself. The solution it to take advantage from the fact that you can chain promises:

function sort<T>(list: T[], fn: (item: T) => string | number): T[];
function sort<T>(list: Promise<T[]>, fn: (item: T) => string | number): Promise<T[]>;
function sort<T>(list: Promise<T[]> | T[], fn: (item: T) => string | number): Promise<T[]> | T[] {
  const doPlainArraySort = (items: T[]): T[] => { /* Do your sorting algorithm here */ };

  if (list instanceof Promise) {
    return list.then(doPlainArraySort);
  }

  return doPlainArraySort(list);
}

The only problem to this approach is that checking for a promise might not be trivial but, otherwise, it works as expected!

carlosV2
  • 1,167
  • 6
  • 15