16

The following code is correct in terms of the type that is returned, because then always return the promise array.

Promise.resolve(['one', 'two'])
.then( arr =>
{
  if( arr.indexOf('three') === -1 )
    return Promise.reject( new Error('Where is three?') );

  return Promise.resolve(arr);
})
.catch( err =>
{
  console.log(err); // Error: where is three?
})

TypeScript throw error:

The type argument for type parameter 'TResult' cannot be inferred from the usage. Consider specifying the type arguments explicitly. Type argument candidate 'void' is not a valid type argument because it is not a supertype of candidate 'string[]'.

But in reality, then never will return void.

I can explicitly specify type .then<Promise<any>>, but it's more like a workaround, not the right solution.

How to write this right?

2 Answers 2

12

You should not return Promise.resolve and Promise.reject inside a promise chain. The resolve should be driven by simple return and reject should be driven by an explicit throw new Error.

Promise.resolve(['one', 'two'])
.then( arr =>
{
  if( arr.indexOf('three') === -1 )
    throw new Error('Where is three?');

  return arr;
})
.catch( err =>
{
  console.log(err); // Error: where is three?
})

More

More on promise chaining https://basarat.gitbooks.io/typescript/content/docs/promise.html

Sign up to request clarification or add additional context in comments.

2 Comments

As a best practice, of course you are right, but at the same time there is no reason why you could not return Promise.resolve() and/or Promise.reject() from within a then handler, and the OP has a legitimate question as to why TypeScript is unhappy about that.
What is the reason why "you should not return Promise.resolve and Promise.reject"? I don't understand why anyone would consider that "a best practice". Chainability is at the core of promises, and it's a great principle. Why would you throw an exception that will be converted into a rejected promise instead of creating the rejected promise yourself?
3

Typescript is complaining about the difference in return type between your Promise.reject return value (Promise<void>) and your Promise.resolve value (Promise<string[]>).

Casting your then call as .then<Promise<void | string[]>> will let the compiler know of the union return type.

as @basarat notes, you should just throw an error instead of using Promise.reject (which will be passed to whatever catch handler is provided).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.