I was having the same problem as you, and then finally managed to resolve it after reading the documentation in the TS mongoose typings (which I didn't know about before, and I'm not sure how long the docs have been around), specifically this section.
As for your case, you'll want to follow a similar pattern to what you currently have, although you'll need to change a few things in both files.
IUser file
- Rename
IUser
to IUserDocument
. This is to separate your schema from your instance methods.
- Import
Document
from mongoose.
- Extend the interface from
Document
.
Model file
- Rename all instances of
IUser
to IUserDocument
, including the module path if you rename the file.
- Rename only the definition of
IUserModel
to IUser
.
- Change what
IUser
extends from, from IUserDocument, Document
to IUserDocument
.
- Create a new interface called
IUserModel
which extends from Model<IUser>
.
- Declare your static methods in
IUserModel
.
- Change the
User
constant type from Model<IUserModel>
to IUserModel
, as IUserModel
now extends Model<IUser>
.
- Change the type argument on your model call from
<IUserModel>
to <IUser, IUserModel>
.
Here's what your model file would look like with those changes:
import * as bcrypt from 'bcryptjs';
import { Document, Schema, Model, model } from 'mongoose';
import { IUserDocument } from '../interfaces/IUserDocument';
export interface IUser extends IUserDocument {
comparePassword(password: string): boolean;
}
export interface IUserModel extends Model<IUser> {
hashPassword(password: string): string;
}
export const userSchema: Schema = new Schema({
email: { type: String, index: { unique: true }, required: true },
name: { type: String, index: { unique: true }, required: true },
password: { type: String, required: true }
});
userSchema.method('comparePassword', function (password: string): boolean {
if (bcrypt.compareSync(password, this.password)) return true;
return false;
});
userSchema.static('hashPassword', (password: string): string => {
return bcrypt.hashSync(password);
});
export const User: IUserModel = model<IUser, IUserModel>('User', userSchema);
export default User;
And your (newly renamed) ../interfaces/IUserDocument
module would look like this:
import { Document } from 'mongoose';
export interface IUserDocument extends Document {
email: string;
name: string;
password: string;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…