TypeScript: Should awaiting a non-Promise value be an error?

TypeScript Version:

1.9.0-dev.20160426

Code

var x = await 5;

Currently this compiles just fine and behaves correctly at runtime. But is there a situation where the user would want to deliberately await a non-Promise? Or should it be a compiler error?


I thought of:

  1. Normalizing a sync-or-async value:

    declare function mayReturnSyncOrAsyncResult(): number | Promise<number>;
    
    var result = await mayReturnSyncOrAsyncResult(); // number
    

    Either await could still be allowed for unions that contain Promise, or the user could be required to use await Promise.resolve instead of just await.

  2. Extracting the value of a thenable:

    declare function foo(): bluebird.Promise<number>;
    
    var result = await foo(); // number
    

    Again await could still be allowed, or the user could be required to use await Promise.resolve

  3. Deliberately introducing a yield point to make the rest of the function be a separate async continuation. I’m not sure if such a use actually exists in the wild. If it does exist, it too can be handled by await Promise.resolve

The downside of await Promise.resolve is that it introduces one extra Promise, since await will wrap the awaited value in one anyway.

I’m not completely convinced one way or the other. Opening this issue to get TS team’s and other people’s thoughts.


Alternatively I suppose we can make a tslint rule for “stricter awaits” or something.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (15 by maintainers)

Most upvoted comments

Rumor has it tslint is getting type-based rules in the near future thanks to some work from the Angular team, so that might be a good place to go.

Would be great if there was a flag for raising an error.

Main points from discussion:

  • Not necessarily clear this an error (maybe you intend to effectively yield)
  • What if the awaited expression is a type parameter? Not clear how to determine if that’s an error or not
  • We clearly want to allow await T | Promise<T> (for reasons @bterlson mentioned above) but then it’s weird to allow await Promise<T> but disallow await T since we’re effectively saying either might happen

We can’t tell that you definitely meant to not await any arbitrary value, so disallowing it isn’t something we can do for certain.