-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Mongoose version
6.4.3
Node.js version
18.4.0
MongoDB server version
5.0
Description
Using Model.exists to check if a document exists with the specified query is meant to return the Document's _id if it exists and null otherwise.
But I get a TS error when accessing the _id because it's not the expected value type.
When I read the types to understand the error in these lines,
Lines 308 to 313 in db1ba6e
| /** | |
| * Returns a document with its `_id` if at least one document exists in the database that matches | |
| * the given `filter`, and `null` otherwise. | |
| */ | |
| exists(filter: FilterQuery<T>, callback: Callback<Pick<Document<T>, '_id'> | null>): QueryWithHelpers<Pick<Document<T>, '_id'> | null, HydratedDocument<T, TMethodsAndOverrides, TVirtuals>, TQueryHelpers, T>; | |
| exists(filter: FilterQuery<T>): QueryWithHelpers<Pick<Document<T>, '_id'> | null, HydratedDocument<T, TMethodsAndOverrides, TVirtuals>, TQueryHelpers, T>; |
The first parameter in the
Document class is expected to be _id's type. But the T variable that's passed is the Schema's resolved type.Lines 13 to 23 in db1ba6e
| /** | |
| * Generic types for Document: | |
| * * T - the type of _id | |
| * * TQueryHelpers - Object with any helpers that should be mixed into the Query type | |
| * * DocType - the type of the actual Document created | |
| */ | |
| class Document<T = any, TQueryHelpers = any, DocType = any> { | |
| constructor(doc?: any); | |
| /** This documents _id. */ | |
| _id?: T; |
From the documatation,
Under the hood,
MyModel.exists({ answer: 42 })is equivalent toMyModel.findOne({ answer: 42 }).select({ _id: 1 }).lean()
So the RequireOnlyTypedId type could be better to use as the Model.exists return type because the _id property always exists and the returned document is always a POJO unless it's not found then null.
Lines 117 to 119 in db1ba6e
| export type RequireOnlyTypedId<T> = T extends { _id?: infer U; } | |
| ? Required<{ _id: U }> | |
| : { _id: Types.ObjectId }; |
Then the method definition would be something like,
exists(filter: FilterQuery<T>, callback: Callback<RequireOnlyTypedId<T> | null>): QueryWithHelpers<RequireOnlyTypedId<T> | null, HydratedDocument<T, TMethodsAndOverrides, TVirtuals>, TQueryHelpers, T>;
exists(filter: FilterQuery<T>): QueryWithHelpers<RequireOnlyTypedId<T> | null, HydratedDocument<T, TMethodsAndOverrides, TVirtuals>, TQueryHelpers, T>; Steps to Reproduce
const schema = new mongoose.Schema({ name: String });
const Model = mongoose.model('Model', schema);
Model.exists({ name: "Hey!" }).then(doc => {
if (doc != null) {
const ID: mongoose.Types.ObjectId = doc._id;
// Type '{ name?: string | undefined; } | undefined' is not assignable to type 'ObjectId'.
// Type 'undefined' is not assignable to type 'ObjectId'.ts(2322)
}
});Expected Behavior
For the _id property to be the Document's _id type not the entire document type.