Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

await-promise is incompatible with the Promise/A+ spec #3512

Closed
alexandru opened this issue Nov 24, 2017 · 7 comments
Closed

await-promise is incompatible with the Promise/A+ spec #3512

alexandru opened this issue Nov 24, 2017 · 7 comments

Comments

@alexandru
Copy link

alexandru commented Nov 24, 2017

Bug Report

  • TSLint version: 5.8.0
  • TypeScript version: 2.6.1

TypeScript code being linted

  const tweetsIterator = twitterClient.scanUserTimeline(account.twitter)
  while (true) {
    const tweets = await tweetsIterator.next()
    if (tweets.value && tweets.value.length) {
      await db.bulkInsertTweets(twitterArchiveIndex, tweets.value)
    }
    if (tweets.done) {
      break
    }
  }

Actual behavior

Invalid 'await' of a non-Promise value. (await-promise)
  68 |       const tweetsIterator = twitterClient.scanUserTimeline(account.twitter)
  69 |       while (true) {
> 70 |         const tweets = await tweetsIterator.next()
     |                       ^
  71 |         if (tweets.value && tweets.value.length) {
  72 |           await db.bulkInsertTweets(twitterArchiveIndex, tweets.value)
  73 |         }

Expected behavior

The error is triggered because the object awaited is a Funfix Future which does not inherit from Promise.

According to the Promises/A+ specification the Promise class is NOT required for await to work. You only need a "thenable" object, meaning a type that implements then with the described behavior.

In TypeScript this is exposed as PromiseLike:

interface PromiseLike<T> {
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onfulfilled The callback to execute when the Promise is resolved.
     * @param onrejected The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     */
    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}

Possibly related: #3381

Please make this check look for PromiseLike and not for Promise.

Thanks,

@ajafff
Copy link
Contributor

ajafff commented Nov 24, 2017

You can configure what the rule should treat as promise: https://palantir.github.io/tslint/rules/await-promise/

@alexandru
Copy link
Author

alexandru commented Nov 24, 2017

What's the motivation for Thenable to not be the default?

@ajafff
Copy link
Contributor

ajafff commented Nov 24, 2017

The rule doesn't check for assignability / compatibility. It just checks the name. Thenable is a builtin type and even if it was, you are not required to implement that interface.

@alexandru
Copy link
Author

You mean it literally checks that the type's name is that string?

@ajafff
Copy link
Contributor

ajafff commented Nov 24, 2017

You mean it literally checks that the type's name is that string?

Yep, it checks the name of every base type and recurses into union and intersection types.

adidahiya added a commit that referenced this issue Nov 28, 2017
@adidahiya
Copy link
Contributor

How's this for a docs update to clarify the issue? #3519

adidahiya added a commit that referenced this issue Nov 28, 2017
@alexandru
Copy link
Author

Thanks for the clarifications @ajafff, @adidahiya.

Cheers,

HyphnKnight pushed a commit to HyphnKnight/tslint that referenced this issue Apr 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants