Closed heilmela closed 2 years ago
Defining the instance methods, statics and query helpers directly in the Schema options will cause them to be inferred automatically.
Read the Documentation. https://mongoosejs.com/docs/guide.html#methods.
If you must, you can extract the inferred methods/statics/query helpers with the ObtainSchemaGeneric
. That's how the InferSchemaType
works as well
Defining the instance methods, statics and query helpers directly in the Schema options will cause them to be inferred automatically.
Read the Documentation. https://mongoosejs.com/docs/guide.html#methods.
If you must, you can extract the inferred methods/statics/query helpers with the
ObtainSchemaGeneric
. That's how theInferSchemaType
works as well
I can't seem to get this to work with my instance methods, but I'm probably doing something wrong. I made this simple schema:
const schema = new Schema(
{
name: { type: String, unique: true, required: true },
},
{
methods: {
someMethod() {
return "test";
},
},
}
);
type User = InferSchemaType<typeof schema>;
And the User type still only contains the name like shown here, no methods:
type User = {
name: string;
}
Wait i just realized that if i remove the InferSchemaType
line in my example, and just let it infer automatically without me doing anything, it includes the instance methods :partying_face:
Im still not sure what exactly im doing wrong, but in my case the inferred Document Type doesnt seem to include instance methods:
// Schema
const schema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true },
avatar: String,
},
{
methods: {
test: (a: string) => a,
},
},
);
const UserModel = mongoose.model('User', schema);
UserModel.findOne()
.exec()
.then((x) => {
// (parameter) x: (mongoose.Document<unknown, any, {
// name: string;
// email: string;
// avatar?: string | undefined;
// }> & {
// name: string;
// email: string;
// avatar?: string | undefined;
// } & {
// _id: mongoose.Types.ObjectId;
// } & {
// ...;
// }) | null
x.test('a');
// Property 'test' does not exist on type
//'(Document<unknown, any, { name: string; email: string; avatar?: string | undefined; }> & { name: string; email: string; avatar?: string | undefined; }
//& { _id: ObjectId; } & { ...; })[]'.
});
@heilmela
I'm not sure, because your commented-out code looks like it's an array, but you're querying the Model with findOne
, so the result could also be null
.
Check if the result is not null
. If that's not the fix, try getting a single document from the result if it's an array with something likex[index]
.
@iammola i updated the comment, it was a false leftover from a previous edit where i used find()
. You are absolutely correct the union with null did produce the error. This works:
UserModel.findOne()
.exec()
.then((x) => {
// (parameter) x: (mongoose.Document<unknown, any, {
// name: string;
// email: string;
// avatar?: string | undefined;
// }> & {
// name: string;
// email: string;
// avatar?: string | undefined;
// } & {
// _id: mongoose.Types.ObjectId;
// } & {
// ...;
// }) | null
if (x !== null) x.test('a');
});
Prerequisites
Issue
So I wanna use the newly added
InferSchemaType
to remove boilerplate interfaces. However im not sure how would one add InstanceMethods, Virtuals, etc. to the Schema without defining the now inferred DocType. When leaving EnforceDocType and Model as defaults, the inferred document type is{ [x: string]: any] }
. Unfortunatly, typescript does not allow to skip generic parameters for now (https://github.com/microsoft/TypeScript/issues/10571)