-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
BSON ObjectId is not compatible with Types.ObjectId #12537
Comments
this is only a problem with the bson-ObjectId and the mongoose-ObjectId
the problem (and typescript error) say that they are not compatible, because the mongoose side expects a mongoose object id (which is a extension from the mongodb objectid, which is a alias of bson's objectid), but you are only giving it a bson objectid, which does not have all the properties from a mongoose objectid
as a aside, what version were you upgrading from? this type may become supported in the future, but (at least i) would recommend to switching over to only use the mongoose types (which are the proper type) |
I was upgrading from 5.13.13. What I don't understand is why the types are not compatible given that it's actually the same underlying object in JavaScript. Digging more about it seems like mongoose is monkey patching bson ObjectId by adding
so feels like it should try and patch bson ObjectId namespace and add that |
true, mongoose is monkey-patching
mongodb's ObjectId (is from what i know) a alias of bson's ObjectId (a reexport) TL;DR: at runtime those "3" ObjectId's are the same object, but in types mongoose is extending from the mongodb one Lines 82 to 84 in 95496c8
and classes are "downwards compatible", but not "upwards compatible" (the latter is which your code is trying to do: trying to assign a "lower" class to a "upper" one) to clarify: with "upwards" and "downwards" i mean inheritance chain where the top is the class that extended from a "lower" class this at least explains the |
I solved the issue with module augmentation, which is what I feel like mongoose should be doing as well, to match what it does in the runtime.
|
I'm unable to repro this. The following script compiles correctly with Mongoose 6.6.5 and TypeScript 4.8.4: import { model, Schema, Types } from 'mongoose';
import { ObjectId } from 'bson';
// 1. Create an interface representing a document in MongoDB.
interface IUser {
name: string;
email: string;
organizationId: ObjectId;
}
// 2. Create a Schema corresponding to the document interface.
const userSchema = new Schema<IUser>({
name: { type: String, required: true },
email: { type: String, required: true },
// And `Schema.Types.ObjectId` in the schema definition.
organizationId: { type: Schema.Types.ObjectId, ref: 'Organization' }
});
const User = model<IUser>('User', userSchema);
const user = new User()
// Property '_id' is missing in type ('bson").ObjectID' but required in type 'import("mongoose").Types.ObjectId'.
user.organizationId = new ObjectId() Output shows no errors:
Can you please modify the script to demonstrate your issue? |
This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days |
This issue was closed because it has been inactive for 19 days since being marked as stale. |
@vkarpov15 is possible re-open it again? import { model, Schema, Types } from 'mongoose';
import { ObjectId } from 'bson';
// 1. Create an interface representing a document in MongoDB.
interface IUser {
name: string;
email: string;
// This needs to be Types.ObjectId so it will be different types
organizationId: Types.ObjectId;
}
// 2. Create a Schema corresponding to the document interface.
const userSchema = new Schema<IUser>({
name: { type: String, required: true },
email: { type: String, required: true },
// And `Schema.Types.ObjectId` in the schema definition.
organizationId: { type: Schema.Types.ObjectId, ref: 'Organization' }
});
const User = model<IUser>('User', userSchema);
const user = new User()
// Property '_id' is missing in type ('bson").ObjectID' but required in type 'import("mongoose").Types.ObjectId'.
user.organizationId = new ObjectId() The key on the example was type (as recommended by the docs) are Types.ObjectId // This needs to be Types.ObjectId so it will be different types
organizationId: Types.ObjectId;
// that should still allow to assign
user.organizationId = new ObjectId() gh-12537.ts:23:1 - error TS2741: Property '_id' is missing in type 'import("/home/test/example/node_modules/bson/bson").ObjectID' but required in type 'import("mongoose").Types.ObjectId'.
23 user.organizationId = new ObjectId()
~~~~~~~~~~~~~~~~~~~
node_modules/mongoose/types/types.d.ts:83:7
83 _id: this;
~~~
'_id' is declared here.
Found 1 error in gh-12537.ts:23 |
can confirm reproduction repository & branch: https://github.com/typegoose/typegoose-testing/tree/mongoose12537 like i said in my earlier comment, these classes are the same at runtime, but in types they are only downwards compatible (ie a a solution to this would be for mongoose to patch the bson namespace directly with this change |
I do agree, given that mongoose is expanding the functionality it should also adjust the interface to make the two types compatible. At the very least adding documentation about and how to solve it for the user, would save a lot of time. Currently I'm using a declaration file, to do module augmentation, that will fix the issue. Example file:
import mongoose from 'mongoose';
/** Augment bson ObjectId due to Mongoose doing monkey patching, but not updating interface **/
declare module "bson" {
export class ObjectId extends mongoose.Types.ObjectId {
_id: this;
}
} |
i dont recommend to do this, remove the |
This comment was marked as outdated.
This comment was marked as outdated.
when i tested locally in my reproduction repository i could not originally produce the error, but when i tried to make a mongoose PR it appeared. Turns out that you need to do a |
● Test suite failed to run src/impl/mongoose/dao/MongooseDaoFactory.ts:45:5 - error TS2322: Type 'OfferDao' is not assignable to type 'IOfferDao<ObjectId, IOffer<ObjectId>>'. Types of property 'loadSubOffers' are incompatible. Type '(parentOfferId: ObjectId) => Promise<IMongooseOffer[]>' is not assignable to type '(parentOfferId: ObjectId) => Promise<IOffer<ObjectId>[]>'. Types of parameters 'parentOfferId' and 'parentOfferId' are incompatible. Type 'ObjectId' is missing the following properties from type 'ObjectId': _bsontype, id, toHexString, toJSON, and 3 more. 45 return this.offerDao; Known issue: Automattic/mongoose#12711 Automattic/mongoose#12537
I solved this problem downgrade mongodb form v6 to mongodb 5.9.1 |
Prerequisites
Mongoose version
6.6.5
Node.js version
14.19.3
MongoDB server version
4.4
Description
I'm trying to upgrade to v6 of mongoose but keep receiving multiple errors related to ObjectId
That was new a error showing up after upgrade in a lot of places, LeanDocument 🤔 ?
I was expecting it to be original ObjectId, but I'm not sure if there is any way to change that other than updating interface?
Then that lead me to reading up recommend logic for ObjectId at this page: ObjectIds and Other Mongoose Types
Suggested ObjectId types
To define a property of type
ObjectId
, you should useTypes.ObjectId
in the TypeScript document interface. You should useObjectId
orSchema.Types.ObjectId
in your schema definition.Current codebase setup
Current approach is to use bson ObjectId as interface type and
Schema.Types.ObjectId
as schema type, therefore this will require to update all interfaces to useTypes.ObjectId
instead of bson ObjectId.Now this is where the real problem is, seems like Types.ObjectId is not actually compatible with bson ObjectId due to required
_id
property. That would require huge amount of changes to replacenew ObjectId()
withnew Types.ObjectId()
. Is this an overlook? What is the reason Types.ObjectId is not compatible the actual underlying ObjectId class?Next steps
Determine if this an issue with queries now returning
LeanDocument<ObjectId>
instead ofObjectId
? or incompatibility betweenTypes.ObjectId
and bsonObjectId
?I'm surprised this have not yet come up more 🤔
Let me know what is the best way to processed with upgrade!
Steps to Reproduce
Expected Behavior
bson
ObjectId should be accepted as Types.ObjectId interface or query should not returnLeanDocument<ObjectId>
The text was updated successfully, but these errors were encountered: