Mongoose模型无法访问实例方法correctPassword问题
解决Mongoose实例方法在TypeScript中类型不识别的问题
问题核心是TypeScript无法识别你在Mongoose Schema上定义的correctPassword实例方法,因为IUser接口仅定义了文档属性,未包含方法类型。以下是具体修复步骤:
1. 定义实例方法的类型接口
创建专门接口描述实例方法,让TypeScript识别这些方法的类型:
import mongoose from 'mongoose'; import bcryptjs from 'bcryptjs'; import validator from 'validator'; // 用户文档属性接口 interface IUser { name: string; password: string; email: string; subscribers: number; } // 用户实例方法接口 interface IUserMethods { correctPassword(candidatePassword: string): Promise<boolean>; }
2. 关联Schema与方法类型
创建Schema时,通过泛型参数将属性接口和方法接口关联:
const userSchema = new mongoose.Schema<IUser, {}, IUserMethods>({ name: { type: String, required: true, trim: true }, password: { type: String, required: true, minlength: 8, select: false, }, email: { type: String, required: true, trim: true, unique: true, lowercase: true, validate: validator.isEmail, }, subscribers: { type: Number, default: 0, } });
3. 优化实例方法实现
利用this直接访问当前文档的密码,简化方法逻辑:
userSchema.pre('save', async function(next) { if (!this.isModified('password')) { return next(); } this.password = await bcryptjs.hash(this.password, 12); next(); }); userSchema.methods.correctPassword = async function(candidatePassword: string) { return await bcryptjs.compare(candidatePassword, this.password); };
4. 定义带方法类型的Model
创建Model时指定正确泛型,确保返回的文档包含实例方法:
type UserModel = mongoose.Model<IUser, {}, IUserMethods>; export const User = mongoose.model<IUser, UserModel>('User', userSchema);
5. 修正控制器调用逻辑
调整调用方式,同时提前判断user是否存在避免空值错误:
public readonly login = async (req: Request, res: Response) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ message: '请求体必须包含邮箱和密码' }); } const user = await User.findOne({ email }).select('+password'); if (!user) { return res.status(401).json({ message: '邮箱或密码错误' }); } const passwordMatch = await user.correctPassword(password); if (!passwordMatch) { return res.status(401).json({ message: '邮箱或密码错误' }); } const token = this.signToken(user._id); return res.status(200).json({ token }); };
关键说明
- Mongoose泛型参数中,第二个为静态方法类型(此处留空
{}),第三个为实例方法类型,需严格匹配接口定义。 - 提前判断
user是否存在,可避免运行时空值调用方法的错误。
内容的提问来源于stack exchange,提问作者István Jódi
相关产品推荐
相关产品推荐

