Repository navigation
Should awaiting a non-Promise value be an error? #8310
Description
Activity
But is there a situation where the user would want to deliberately await a non-Promise? Or should it be a compiler error?
Yes. When the API consumer wants a promise but the API provider doesn't need to be async. The provider code can then just
await🌹instead of
function foo(){ return Promise.resolve(3); }
you get to
async function foo(){ return await 3; }
Arnavion commented
on Apr 26, 2016 ContributorAuthorMore actionsBasarat Ali Syed (@basarat) That should be
async function foo() { return 3; }
That should be return 3
Indeed. Sorry. I know I should have been sleeping at that time 🌹
// CC Brian Terlson (@bterlson)
I believe it is not an error to await a non-thenbale non-promise object. awaiting a literal as in the example should be equivalent to
await Promise.resolve(3). Brian Terlson (@bterlson) can point to the spec details.one thing to note,
var x = await 5;is not the same asvar x = 5;;var x = await 5;will assignx5in the next tern, where asvar x = 5;will evaluate immediately.- addedBy DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
on Apr 26, 2016 Arnavion commented
on Apr 26, 2016 ContributorAuthorMore actionsYes, I said all that in the OP.
But is there a situation where the user would want to deliberately await a non-Promise
This is the heart of the question by Arnav Singh (@Arnavion) ^.
Me : I can't think of a good reason. The only use case (next tern) is not one the user should be depending upon. There might be some obscure debounce style stuff that one can cook up 🌹
Brian Terlson (@bterlson), can you shed some light on the rational/motivating use cases for the current design?
Just some anecdotal info: I got unwanted behavior when writing my first TypeScript program, since in many libs the TS version uses *Async names for the Promise-returning version of the function.
So since the callback was optional, I "awaited" on void and then the program would continue too early...
So if there no real reason to keep this behavior, I can assure you that this has already created some bug (even though luckily only during development).
The goal of the current semantics isn't to allow uselessly awaiting known synchronous values but instead to allow awaiting maybe-promises and to align with the semantics of various existing promise utilities including Promise.resolve (promises and thenables unwrapped, values passed through) and then handlers (returned promises and thenables unwrapped, values passed through).
Thinking about this more, this could be enforced under a flag, by default if the compiler can attest that the type of await expression can not be a promise, then it should report an error, if the flag is set, the error reporting is skipped.
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensusand removedBy DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
on Apr 28, 2016 - addedWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bugand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Jun 9, 2016 RyanCavanaugh commented
on Jun 9, 2016 MemberMore actionsMain 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 Brian Terlson (@bterlson) mentioned above) but then it's weird to allowawait Promise<T>but disallowawait Tsince 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.
Reacted by Martin Helmich- Not necessarily clear this an error (maybe you intend to effectively
but then it's weird to allow
await Promise<T>but disallowawait Tsince we're effectively saying either might happenI dunno, atleast to me it doesn't seem weird.
Would be great if there was a flag for raising an error.
Reacted by Pablo MoleriRyanCavanaugh commented
on Jul 25, 2016 MemberMore actionsRumor has it
tslintis 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.Reacted by AJ RichardsonRumor has it tslint is getting type-based rules
Indeed it is. The reason why I've dropped my usage of ntypescript (which could support ts extension) and moved to a simpler automation of bring your own typescript : https://github.com/basarat/byots (as the extension can now be done using tslint) and also working on first class integration into alm : alm-tools/alm#155 🌹
- locked and limited conversation to collaborators
on Jun 19, 2018
TypeScript Version:
1.9.0-dev.20160426
Code
Currently this compiles just fine and behaves correctly at runtime. But is there a situation where the user would want to deliberately
awaita non-Promise? Or should it be a compiler error?I thought of:
Normalizing a sync-or-async value:
Either
awaitcould still be allowed for unions that containPromise, or the user could be required to useawait Promise.resolveinstead of justawait.Extracting the value of a thenable:
Again
awaitcould still be allowed, or the user could be required to useawait Promise.resolveDeliberately 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.resolveThe downside of
await Promise.resolveis that it introduces one extra Promise, sinceawaitwill 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.