Is there any way to define / amend an interface or type as to assert that a document will be populate in typescript using mongoose?
e.g.
interface ISchool {
name: string;
address; string;
}
interface IPerson {
name: string;
school?: PopulatedDoc<ISchool & Document>
}
const PersonSchema: Schema<IPerson> = new Schema<IPerson>({
name: { type: String },
school: { type: Schema.Types.ObjectId, ref: 'School' }
})
const Person = mongoose.model<IPerson>('Person', PersonSchema);
export default Person
Then essentially if we ever interact with a Person document, there is no way of knowing if the school
property is populated of not.
eg.
const person = await Person.findOne({});
if (person.school) { . . . } // is `school` an ObjectId or a Document?
and
const person = await Person.findOne({}, undefined, { populate: { path: 'school', model: 'School'} });
if (person.school) { . . . } // is `school` an ObjectId or a Document?
Is there any way to assert that a document property has been populated?
Thanks
From the populate-with-typescript documentation, we can:
add a generic parameter
Paths
to thepopulate()
import mongoose, { Types } from 'mongoose';
interface ISchool {
name: string;
address: string;
}
interface IPerson {
name: string;
school?: Types.ObjectId;
}
const PersonSchema: mongoose.Schema<IPerson> = new mongoose.Schema<IPerson>({
name: { type: String },
school: { type: mongoose.Schema.Types.ObjectId, ref: 'School' },
});
const Person = mongoose.model<IPerson>('Person', PersonSchema);
(async function run() {
const person1 = await Person.findOne({});
person1?.school; // school is ObjectId
const person2 = await Person.findOne({}).populate<{ school: ISchool }>({ path: 'school', model: 'School' });
person2?.school; // scholl is ISchool
})();