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

async/await can not be used in class method definition(without method body) #22035

Closed
vincedan opened this issue Feb 19, 2018 · 10 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@vincedan
Copy link

vincedan commented Feb 19, 2018

`class BaseClass {
async created: () => Promise< string >;
}

BaseClass.prototype.created = () => {
return await Promise.resolve("OK");
};`

Severity Code Description Project File
Error TS1042 'async' modifier cannot be used here. TypeScript Virtual Projects
Error TS2322 Type '() => string' is not assignable to type '() => Promise'. Type 'string' is not assignable to type 'Promise'.
Error TS1308 'await' expression is only allowed within an async function. TypeScript Virtual Projects

@vincedan
Copy link
Author

can not change title... here "class method" is not meaning static method... my sample is not also... should be instance/prototype function(method), I guess, for static method of class should have the same issue.

@yume-chan
Copy link
Contributor

yume-chan commented Feb 19, 2018

Your usage is totally wrong.

The created member in your BaseClass class is a field, with type of () => Promise<string>, how can a field to be async?

The async keyword must be used with a function, like async function doSomething() { /* ... */ } or async () => { /* ... */ }

The await keyword can only be used within the body of an async function, like the examples above.

EDIT: If you want an async instance method, it should be async doSomething(): Promise<string> { return "OK"; }, always strip the function keyword from the declaration.

In addition, for an async function, the return type must be Promise<T>, but you only need to return a value of type T, the compiler/runtime will create a Promise to wrap your return value automatically.

One more thing, you should post your problem to StackOverflow if you don't really understand some feature or don't know why it doesn't work. The GitHub Issue Tracker should only be used when you are at least 90% sure that there is a bug in the project.

@vincedan
Copy link
Author

vincedan commented Feb 19, 2018

thanks @yume-chan for your reply. I knew async keywords will wrap function return value as Promise if it is not. here just a sample to demonstrate. the key thing here is

"The async keyword must be used with a function, like async function doSomething() { /* ... / } or async () => { / ... */ } The await keyword can only be used within the body of an async function, like the examples above."

if this is ms offically reply, I will close this issue (I reserve my opinion).

@ghost ghost added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 20, 2018
@vincedan
Copy link
Author

vincedan commented Feb 20, 2018

thanks @andy-ms 's response.
if without this feature, I can only use promise-then pattern in concrete method.
for choosing typescript, means providing type. not give limitation. right now, typescript provides definite method signature(without methodbody) in class definition, it works fine. but could not use async, I have to say this is a bad design. I close this post but still keep my opinions.

@yume-chan
Copy link
Contributor

Again, your opinion is totally WRONG.

async keyword and Promise are two unrelated things. A function returns a Promise doesn't mean it must be async.


The async and await keywords are syntactic sugar for using Promise without chaining then() calls.

async function doSomething() {
    await Promise.resolve("OK");
    alert("done");
}

Is semantically equals to

function doSomething() {
    Promise.resolve("OK").then(() => {
        alert("done");
    });
}

So as I have said above, your field created cannot be marked with async because it's not a function, and your value for BaseClass.prototype.created must be marked with async to use await.

class BaseClass {
    created: () => Promise<string>; // NO async here
}

BaseClass.prototype.created = async () => { // async HERE
    retrun await Promise.resolve("OK");
}

Or, you should just declare your function body in the class

class BaseClass {
    async created(): Promise<string> {
        retrun await Promise.resolve("OK");
    }
}

Which I have also said above. (Why don't you do this when you are already using class?)

@vincedan
Copy link
Author

Hi, yume-chan , I guess you still don't understand my question. [created] here is not a field. it is method with itself method signature... I think I need to reopen this question. need senior stuff to check it again.
I was wondered that I need to paste the source code.please check the following.
`class BaseClass {
public async created(str: string) { }; //OK
public created1: (str: string) => void; //OK
public async created2: (str: string) => void; //Wrong TS1042:'async' modifier cannot be used here

}
BaseClass.prototype.created = async (str2) => {
//OK
};
BaseClass.prototype.created1 = (str2) => {
//OK
};
BaseClass.prototype.created2 = async (str2) => {
//OK
};`

@vincedan vincedan reopened this Mar 13, 2018
@yume-chan
Copy link
Contributor

yume-chan commented Mar 13, 2018

Please check ecma-262 chapter 14.6 Class Definitions, if it's a method definition, it must follow the syntax defined in 14.3 Method Definitions, which requires a parameter list and a method body. I cannot see both on your created field.

Class fields is a TypeScript extension and a stage 3 proposal tc39/proposal-class-fields, your created field clearly fits with these definitions, with TypeScript access modifier and type declaration.

If you cannot read ecma-262, I think there is nothing more we can talk. I have unsubscribed this issue.

@yortus
Copy link
Contributor

yortus commented Mar 13, 2018

@vincedan if you want to declare a method, do it inline like @yume-chan showed:

class BaseClass {
    async created() {
        return await Promise.resolve("OK");
    }
}

If you want an instance property that is an async function, do it like this:

class BaseClass {
    created = async () => await Promise.resolve("OK");
}

If you are trying to create an abstract base class to implement in other classes, do it like this:

abstract class BaseClass {
    abstract created(): Promise<string>;
}

class DerivedClass extends BaseClass {
    async created() {
        return await Promise.resolve("OK");
    }
}

@vincedan
Copy link
Author

@yortus thanks. I need abstract interface defined here. I wanna use typescript strong type Intellisense but without method body. the third solution give me another hint. thanks again.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants