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.