Home > front end >  Typescript return type changes with async keyword
Typescript return type changes with async keyword

Time:06-14

This seems really strange to me.

I have a function to count documents from a collection

async getDocCount(): Promise<number> {
   return MyModel.countDocuments({});
}

All good. But there's no reason to have async when you are returning a Promise. So I remove async and typescript complains. I hover over the return type and it is now something crazy like

mongoose.QueryWithHelpers<number, mongoose.Document<mongoose.Types.ObjectId, BeAnObject, any> & MyModel & IObjectWithTypegooseFunction & {
    ...;
}, BeAnObject, DocumentType<...>>

What's going on here? Why does removing async affect the return type?

CodePudding user response:

MyModel.countDocuments({}) returns a Query, and "Queries are not promises".

They are thenable so you can await them, but if you want a proper promise, you need to call exec() on it:

return MyModel.countDocuments({}).exec();

Although I'm not sure if that will yield the proper return type (Promise<number>) for TS, you may have to use return await MyModel.countDocuments({}) instead.

CodePudding user response:

Putting async always makes the function return a Promise. From MDN

Return value

A Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.

If your function compiled with async, then that means MyModel.countDocuments({}) returns something compatible with number, not Promise<number>, and then the async keyword automatically added the Promise part itself.

I'm not familiar with Mongoose, so I can't speak to the keyboard smash of a type signature that the library seems to be returning. But Typescript has some very powerful rules for what types are compatible with what other types, so it's very possible that that complicated Mongoose type is actually compatible with number.

I do challenge your assertion that the countDocuments function returns a promise to begin with, though, as Typescript seems to be indicating the opposite in its error.

  • Related