I'm taking advantage of mongoose class schemas .
And using TypeScript for my Node project.
I've followed Mongoose the Typescript way...? to make sure my Model is aware of the schema I've defined, So I've auto-completion etc..
However it becomes more tricky with schema class. As written in their docs:
The loadClass() function lets you pull in methods, statics, and virtuals from an ES6 class. A class method maps to a schema method, a static method maps to a schema static, and getters/setters map to virtuals.
So my code looks something like:
interface IUser extends mongoose.Document {
firstName: string,
lastName: string
};
const userSchema = new mongoose.Schema({
firstName: {type:String, required: true},
lastName: {type:String, required: true},
});
class UserClass{
static allUsersStartingWithLetter(letter: string){
return this.find({...});
}
fullName(this: IUser){
return `${this.firstName} ${this.lastName}`
}
}
userSchema.loadClass(UserClass);
const User = mongoose.model<IUser>('User', userSchema);
export default User;
My goal is that TypeScript will understand that:
User
has a method allUsersStartingWithLetter
User
instance has a method fullName
In the current configuration it does not. I was not able to accomplish it myself.
Do you really need to use classes? I could accomplish this using interfaces without using classes to do it. Here's an example:
/* eslint-disable func-names */
import mongoose from 'mongoose';
export interface Foo {
id?: string;
name: string;
createdAt?: Date;
updatedAt?: Date;
}
export type FooDocument = mongoose.Document & Foo;
const fooSchema = new mongoose.Schema(
{
name: { type: String, required: true },
},
{ timestamps: true }
);
fooSchema.methods.bar = function (): void {
const foo = this as FooDocument;
foo.name = 'bar';
};
const FooModel = mongoose.model<FooDocument>('foos', fooSchema);
export default FooModel;
This way you can use the Foo
interface for methods with the inversion depedency. Them in your repository will return Foo
instead of FooDocument...
Extra: If you use lean()
in your database requests you return exactly the Foo
interface. More information for lean here
Have you considered adding extends mongoose.Model
to the UserClass
?
class UserClass extends mongoose.Model<IUser> {
static allUsersStartingWithLetter(letter: string){
return this.find({...});
}
fullName(this: IUser){
return `${this.firstName} ${this.lastName}`
}
}
Your UserClass
needs to extend Model
from mongoose
. You seem to be missing a bit of required code to make this work for you.
From the link you shared as a reference, here's a guide that should solve your issue with complete code example.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.