You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:27:36