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

The return type of an async function or method must be the global Promise<T> type. #15292

Closed
pierre-H opened this Issue Apr 20, 2017 · 13 comments

Comments

Projects
None yet
10 participants
@pierre-H

pierre-H commented Apr 20, 2017

TypeScript Version: 2.2.2

Code

async getUsername(): string{
    try{
        // I use AsyncStorage from React Native and ReactXP Storage
        let value = await AsyncStorage.getItem('username');
        return value;
    }
    catch(e){
        console.log('caught error', e);
        // Handle exceptions
    }

}

Expected behavior:
getCache return the item
Actual behavior:
This error :

The return type of an async function or method must be the global Promise type.

@blakeembrey

This comment has been minimized.

Contributor

blakeembrey commented Apr 20, 2017

This is the correct behaviour, the return type of an async function is a promise. Use Promise<string> instead of string to indicate that.

@pierre-H

This comment has been minimized.

pierre-H commented Apr 20, 2017

@blakeembrey
Thank you for your answer but if then, I can't create a function which return the username and wait for it execution.

@RyanCavanaugh

This comment has been minimized.

Member

RyanCavanaugh commented Apr 20, 2017

You can. Try it! 😉

@pierre-H

This comment has been minimized.

pierre-H commented Apr 20, 2017

@RyanCavanaugh I did and TypeScript isn't happy because I want that my function return a string but TypeScript wants Promise

@blakeembrey

This comment has been minimized.

Contributor

blakeembrey commented Apr 20, 2017

@pierre-H I'd recommend checking out some JavaScript documentation to better understand how async and promises work. Here's a good place to start: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function. You can't make your function return a string unless all your code is synchronous, in which case you don't need an async function anymore.

@fatcerberus

This comment has been minimized.

fatcerberus commented May 1, 2017

@pierre-H You don't actually have to change any of the code in the function, just change its return type in the declaration to Promise<string>. It's like how async functions in .NET need be declared as returning a Task<T> but the actual code is written as though it returns T directly. The async and await keywords are just sugar for automatic promise wrapping/unwrapping.

@rajkanase

This comment has been minimized.

rajkanase commented Dec 25, 2017

what is the alternative for async await

@bluelovers

This comment has been minimized.

Contributor

bluelovers commented Feb 9, 2018

any options for disable this warning?

@marcj

This comment has been minimized.

marcj commented Mar 13, 2018

To make things clear for anyone looking simply for a solution and are not satisfied by the overly didactic answers:

To make your example workable, change the return type to Promise<string>.

async getUsername(): Promise<string> {
        let value = await AsyncStorage.getItem('username');
        console.log("done", value); //for explaining the following
        return value;
}

However, when calling getUsername() it won't block the execution. So

console.log('1');
console.log(getUsername());
console.log('2');

returns

> "1"
> [object Promise]
> "2"
> "done" "Donald"

As you can see, getUsername() returns now a Promise - always, even tho you returned a string. Javascript will automatically convert it into a Promise, if a non-promise value is returned. Also "2" is printed, although getUsername() might not be executed yet completely, as in the nature of asynchronous javascript.

To make the call "blocking", you need to use await again.

console.log('1');
console.log(await getUsername());
console.log('2');

The result is the same as if you'd use the promise directly via getUsername().then(callback), meaning the execution tree down to the call of getUsername() is asynchronous and you need to call either on every parent method execution await or work with the Promise directly.

The implication is: There is no way to make asynchronous code synchronous with await. Every method calling your async getUsername directly or indirectly becomes automatically async as well.

I mean, I also come from a non-asynchronous programming language and back in the days developed in Javascript like there're no asynchronous operations. However, since the language goes heavily in that direction we need to accept that asynchronous behaviour is here and we need to follow its principles and should not work around that by trying to make code blocking/synchronous again.

what is the alternative for async await

There are 2.

  1. Work with the promise directly, like
getUsername(): Promise<string> {
  return new Promise((resolve, reject) => {
    AsyncStorage.getItem('username').then((username) => {
      resolve(username);
    })
  });
}

However that makes the function still asynchronous.

  1. Make all calls inside getUsername() synchronous.
getUsername(): string {
  return syncStorage.getItem('username');
}

However, that requires that you have a implementation of syncStorage that is truly synchronous.

any options for disable this warning?

No, as this would totally makes no sense at all.

@Matthijs-Wessels

This comment has been minimized.

Matthijs-Wessels commented Apr 12, 2018

Why doesn't putting async in front of the function implicitly convert string to Promise<string>?

This is what I would expect.

@fazelmk

This comment has been minimized.

fazelmk commented Apr 26, 2018

I still don't get why in hell it's a promise. This function should be synchronous

async getUsername(): string{
    try{
        // I use AsyncStorage from React Native and ReactXP Storage
        let value = await AsyncStorage.getItem('username');
        return value;
    }
    catch(e){
        console.log('caught error', e);
        // Handle exceptions
    }

}

The only asynchronous method in it should be blocking the execution because of the await.
This is just stupid. If I want to make an async func sync I must put async/await in all function till the top of calling chain.

it's just STUPID. there is no point in using that shit besides not making promises inside promises.

OR await should be allowed outside async functions or the return of a function shouldn't be a promise just because async is set.

@fatcerberus

This comment has been minimized.

fatcerberus commented Apr 26, 2018

await does not make a function synchronous. From the point of view of the topmost (non-awaiting) caller it behaves like a return and the function resumes “in the background”, controlled by the event loop.

@sbmthakur

This comment has been minimized.

sbmthakur commented Jul 13, 2018

From MDN:

The async function declaration defines an asynchronous function, which returns an AsyncFunction object. An asynchronous function is a function which operates asynchronously via the event loop, using an implicit Promise to return its result. But the syntax and structure of your code using async functions is much more like using standard synchronous functions.

Notice the word implicit? If you don't return a promise, the value you return will automatically be wrapped in a promise. The above-mentioned clarification given by @marcj is pretty much perfect. You may go through this Stack Overflow question if you are still scratching your head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment