Why findById returns (User & { _id: Schema.Types.ObjectId; }) | null they User | null
See original GitHub issueThis is my first time using typescript and mongoose. Here’s my code
type
export interface User extends Document {
_id: ObjectId;
lastName: string;
}
Schema
const userSchema = new Schema<User>({
lastName: { type: String, required: true, trim: true },
});
model
const User = model<User>('user', UserSchema, 'users');
request
const user = await User.findById(userId).exec();
I expect the user
variable to be of type User | null
.but i get (User & {_id: Schema.Types.ObjectId;}) | null
. If I don’t declare _id: ObjectId; then I get ( User & { _id: any; }) | null. I do not know if this is some kind of mistake or it should be like this
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Why findById returns (User & { _id: Schema.Types.ObjectId ...
I expect the user variable to be of type User | null. Well, this just happens to be an invalid expectation. In the...
Read more >findById() is not working properly - Code with Mosh Forum
FindById () is not working and giving null. Where as find(), findOne() works seamlessly. I tried many many solutions to make findById() work....
Read more >findById returns no results even with correct ObjectId #3079
I had a similar issue today. It turns out i saved an _id as a ObjectId string and tried to retrieve id using...
Read more >findById in mongoose returns null for a certain schema ...
Since you haven't specified the _id field in your Schema it will be of type ObjectId . For findById you can pass id...
Read more >Mongoose findById() is returning null? - JavaScript
It's also not of type String but it's an ObjectId . I have no clue what happens if you tell Mongoose to save...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@drewkht 's comment https://github.com/Automattic/mongoose/issues/10987#issuecomment-996170399 is correct. We added a note about the
Schema.Types.ObjectId
vsTypes.ObjectId
distinction in #10949The return type comes from the internal types used by
mongoose.model()
to create theUser
model.Mongoose’s
HydratedDocument<T>
type is used for all documents created/queried by a model of typeModel<T>
. It’s explained further in the linked Mongoose docs.Because the
User
interface extendsDocument
,HydratedDocument<User>
resolves to the Mongoose internal typeRequire_id<User>
, which simply creates a type ~union~ intersectionUser & { _id: User['_id'] }
(to, I assume, ensure that the_id
property is non-nullable - as the_id
property on Mongoose’sDocument
type is nullable).User & { _id: Schema.Types.ObjectId }
is a functionally identical type toUser
, becauseUser
already contains the property_id: Schema.Types.ObjectId
. It definitely looks weird if you’re not familiar with what’s going on behind the scenes or with TypeScript ~unions~ intersections, though.@Darfion - I believe if you just change the
_id
property in theUser
interface toTypes.ObjectId
instead you’ll get the proper results (i.e.const user
will be of typeHydratedDocument<User, ...> | null
).Types.Schema.ObjectId
is only intended to be used within schema definitions, from what I understand.Also, a couple potential issues in the provided examples:
At least in my VS Code with my tsconfig.json, this causes a naming conflict between the
User
interface andconst User
, resulting in the latter resolving toany
. Either renaming the interface to something likeIUser
orconst User
to something likeconst UserModel
would solve this problem.In the above,
userSchema
is used to create the schema, but thenUserSchema
(with an uppercase U) is passed to themodel
function. Because you’re passingUser
as a type parameter to themodel
call (which isn’t necessary if you’re passing the type toSchema
already) you’ll still get a correctly typedModel
from it, but I’m not sure what other issues might arise from not providing an actualSchema
to the function.I rewrote the example like this and it works as expected in my testing: