Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An async function or method must have a valid awaitable return type #10805

Closed
normalser opened this issue Sep 9, 2016 · 4 comments
Closed

An async function or method must have a valid awaitable return type #10805

normalser opened this issue Sep 9, 2016 · 4 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@normalser
Copy link

TypeScript Version: Version 2.1.0-dev.20160908

Code

// A *self-contained* demonstration of the problem follows...
// Example from https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#asyncawait-support-in-es6-targets-node-v4
// target: 'es5'

import * as $Promise from 'bluebird'

// printDelayed is a 'Promise<void>'
async function printDelayed(elements: string[]) {
    for (const element of elements) {
        await delay(200);
        console.log(element);
    }
}

async function delay(milliseconds: number) {
    return new $Promise<void>(resolve => {
        setTimeout(resolve, milliseconds);
    });
}

printDelayed(["Hello", "beautiful", "asynchronous", "world"]).then(() => {
    console.log();
    console.log("Printed every element!");
});

Expected behavior:

Should compile

Actual behavior:

test.ts(4,16): error TS1057: An async function or method must have a valid awaitable return type.
test.ts(11,16): error TS1057: An async function or method must have a valid awaitable return type.
@nippur72
Copy link

nippur72 commented Sep 9, 2016

Does this happens only in target: es5, right?

That was discussed in #6007, if I remember correctly, es5 still needs the return type.

@normalser
Copy link
Author

normalser commented Sep 9, 2016

@nippur72 Yes - it only happens with target: es5 - es6 fine.

Moreover this example works fine with some other project we have.
I found the difference is in types file/definition of bluebird

Old working project is using bluebird with the following older definition:

declare var Promise: PromiseConstructor;

interface PromiseConstructor {
...

interface Promise<T> extends PromiseLike<T>, Promise.Inspection<T> {
....

Latest bluebird doesn't expose that global Promise interface

declare module 'bluebird' {
  class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {
  ...

and I cannot do import * as Promise from 'bluebird' because it will throw an error:
error TS2529: Duplicate identifier 'Promise'. Compiler reserves name 'Promise' in top level scope of a module containing async functions.

@kitsonk
Copy link
Contributor

kitsonk commented Sep 9, 2016

I think if you are polyfilling Promise at runtime for ES5, even though bluebird doesn't by default pollute the global namespace anymore, you will need to load it into the global namespace yourself, as TypeScript expects/needs it in the global namespace.

@nippur72
Copy link

Another strange thing about this "need for return type" is that, if the async function/method is not called withing the compiling project (e.g. it's a library function) then the compiler doesn't complain at all. E.g.

async foo() {} // no error
async bar() {} // error TS1057 
bar();

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Sep 12, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants