Closed
Description
Prerequisites
- I have written a descriptive issue title
Mongoose version
8.2.3
Node.js version
20.14.0
MongoDB version
?
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
14.1
Issue
I have a Mongoose model which has a subdocument. I have a function that queries the model via the .find()
method. The function's output is expected to conform to an output interface, however it is not playing nicely with the the auto-generated TypeScript types for the model. The mongoose docs state: "Each subdocument has an _id
by default", however the types for the DocumentArray
properties returned from a find()
operation do not have _id
marked as required.
This feels like a bug on the Mongoose side but I am new to using the library so it's possible that I'm missing something.
Questions:
- Am I correct that it is safe to assume that any subdocuments will have an
_id
property when a document is retrieved via the.find()
operations? (safe for any situations where I explicitly instruct Mongoose to not place an_id
on the subdocument, of course) - Short of a change in
mongoose
code itself, how can I customize the output of the types in a succinct manner? I'd prefer to not write my own types for the Schema and Model as mongoose does a good job inferring these values and I would like to avoid maintaining redundant code. I see that.find()
is a generic function (link), so I could provide my own type that instructsmongoose
that the_id
is required, however I'm struggling to achieve that.
Simplified example:
import mongoose from 'mongoose';
const ChildSchema = new mongoose.Schema({
name: { type: String, required: true },
});
const ParentSchema = new mongoose.Schema({
_id: { type: String, required: true },
name: { type: String, required: true },
parts: { type: [ChildSchema] },
});
const ParentModel = mongoose.model('Parent', ParentSchema);
export const getParents = async (): Promise<ExpectedParent[]> => {
const parents = await ParentModel.find();
return parents; // TypeScript error here!
};
interface ExpectedParent {
_id: string;
name: string;
parts: Array<{ _id: string; name: string }>;
}
I see the following error from TS:
Type '(Document<unknown, {}, { name: string; _id: string; parts: DocumentArray<{ name: string; }>; }> & { name: string; _id: string; parts: DocumentArray<{ name: string; }>; } & Required<...>)[]' is not assignable to type 'ExpectedParent[]'.
Type 'Document<unknown, {}, { name: string; _id: string; parts: DocumentArray<{ name: string; }>; }> & { name: string; _id: string; parts: DocumentArray<{ name: string; }>; } & Required<...>' is not assignable to type 'ExpectedParent'.
The types returned by 'parts.pop()' are incompatible between these types.
Type '(Subdocument<ObjectId> & { name: string; }) | undefined' is not assignable to type '{ _id: string; name: string; } | undefined'.
Type 'Subdocument<ObjectId> & { name: string; }' is not assignable to type '{ _id: string; name: string; } | undefined'.
Type 'Subdocument<ObjectId> & { name: string; }' is not assignable to type '{ _id: string; name: string; }'.
Types of property '_id' are incompatible.
Type 'ObjectId | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.ts(2322)