GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Should awaiting a non-Promise value be an error? · Issue #8310 · microsoft/TypeScript

Should awaiting a non-Promise value be an error? #8310

New issue
Copy link
New issue
Copy link
Closed
Closed
Should awaiting a non-Promise value be an error?#8310
Copy link
Labels
SuggestionAn idea for TypeScriptAn idea for TypeScriptWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug

Description

@Arnavion
Arnav Singh (Arnavion)
opened on Apr 26, 2016
Issue body actions

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.

Activity

  1. basarat commented on Apr 26, 2016

    @basarat
    Basarat Ali Syed (basarat)
    on Apr 26, 2016
    Contributor
    More actions

    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 🌹

  2. basarat commented on Apr 26, 2016

    @basarat
    Basarat Ali Syed (basarat)
    on Apr 26, 2016
    Contributor
    More actions

    instead of

    function foo(){
          return Promise.resolve(3);
    }

    you get to

    async function foo(){
          return await 3;
    }
  3. Arnavion commented on Apr 26, 2016

    @Arnavion
    Arnav Singh (Arnavion)
    on Apr 26, 2016
    Author
    More actions

    Basarat Ali Syed (@basarat) That should be

    async function foo() {
        return 3;
    }
  4. basarat commented on Apr 26, 2016

    @basarat
    Basarat Ali Syed (basarat)
    on Apr 26, 2016
    Contributor
    More actions

    That should be return 3

    Indeed. Sorry. I know I should have been sleeping at that time 🌹

  5. mhegazy commented on Apr 26, 2016

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Apr 26, 2016
    Contributor
    More actions

    // 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 as var x = 5;; var x = await 5; will assign x 5 in the next tern, where as var x = 5; will evaluate immediately.

  6. Mohamed Hegazy (mhegazy)
    added
    By DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
    on Apr 26, 2016
  7. Arnavion commented on Apr 26, 2016

    @Arnavion
    Arnav Singh (Arnavion)
    on Apr 26, 2016
    Author
    More actions

    Yes, I said all that in the OP.

  8. basarat commented on Apr 26, 2016

    @basarat
    Basarat Ali Syed (basarat)
    on Apr 26, 2016
    Contributor
    More actions

    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 🌹

  9. mhegazy commented on Apr 26, 2016

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Apr 26, 2016
    Contributor
    More actions

    Brian Terlson (@bterlson), can you shed some light on the rational/motivating use cases for the current design?

  10. tp commented on Apr 27, 2016

    @tp
    Timm Preetz (tp)
    on Apr 27, 2016
    More actions

    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).

  11. bterlson commented on Apr 28, 2016

    @bterlson
    Brian Terlson (bterlson)
    on Apr 28, 2016
    Member
    More actions

    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).

  12. mhegazy commented on Apr 28, 2016

    @mhegazy
    Mohamed Hegazy (mhegazy)
    on Apr 28, 2016
    Contributor
    More actions

    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.

  13. Mohamed Hegazy (mhegazy)
    added
    SuggestionAn idea for TypeScriptAn idea for TypeScript
    In DiscussionNot yet reached consensusNot yet reached consensus
    and removed
    By DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
    on Apr 28, 2016
  14. Ryan Cavanaugh (RyanCavanaugh)
    added
    Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
    and removed
    In DiscussionNot yet reached consensusNot yet reached consensus
    on Jun 9, 2016
  15. RyanCavanaugh commented on Jun 9, 2016

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Jun 9, 2016
    Member
    More actions

    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 Brian Terlson (@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.

    Reacted by Martin Helmich
  16. Ryan Cavanaugh (RyanCavanaugh)
    closed this as completedon Jun 9, 2016
  17. Arnavion commented on Jun 9, 2016

    @Arnavion
    Arnav Singh (Arnavion)
    on Jun 9, 2016
    Author
    More actions

    but then it's weird to allow await Promise<T> but disallow await T since we're effectively saying either might happen

    I dunno, atleast to me it doesn't seem weird.

  18. tinganho commented on Jul 25, 2016

    @tinganho
    Tingan Ho (tinganho)
    on Jul 25, 2016
    Contributor
    More actions

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

    Reacted by Pablo Moleri
  19. RyanCavanaugh commented on Jul 25, 2016

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Jul 25, 2016
    Member
    More actions

    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.

    Reacted by AJ Richardson
  20. basarat commented on Jul 25, 2016

    @basarat
    Basarat Ali Syed (basarat)
    on Jul 25, 2016
    Contributor
    More actions

    Rumor 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 🌹

  21. microsoft
    locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    SuggestionAn idea for TypeScriptAn idea for TypeScriptWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.