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

Next.js13.5中TypeScript版Mongoose用户模型方法与虚拟字段异常

问题分析与解决方案

1. 明确Schema的类型定义与this指向

在TypeScript中,Mongoose的实例方法和虚拟字段必须明确指定this的类型,否则TS会错误推断this指向,导致this.salt和this.hashed_password无法正确访问。

正确的TS版模型示例

import mongoose, { Schema, Document } from 'mongoose';
import crypto from 'crypto';

// 定义用户文档接口,包含所有字段与方法声明
interface IUser extends Document {
  hashed_password: string;
  salt: string;
  _password?: string;
  password: string;
  authenticate(plainText: string): boolean;
  encryptPassword(password: string): string;
  makeSalt(): string;
}

const userSchema = new Schema<IUser>({
  hashed_password: { type: String, required: true },
  salt: { type: String, required: true }
});

// 虚拟字段password的setter/getter必须指定this类型
userSchema.virtual('password')
  .set(function(this: IUser, password: string) {
    this._password = password;
    this.salt = this.makeSalt();
    this.hashed_password = this.encryptPassword(password);
  })
  .get(function(this: IUser) {
    return this._password;
  });

// 实例方法同样需要绑定this类型
userSchema.methods.authenticate = function(this: IUser, plainText: string): boolean {
  return this.encryptPassword(plainText) === this.hashed_password;
};

userSchema.methods.encryptPassword = function(this: IUser, password: string): string {
  if (!password) return '';
  try {
    return crypto.createHmac('sha1', this.salt)
      .update(password)
      .digest('hex');
  } catch (err) {
    return '';
  }
};

userSchema.methods.makeSalt = function(this: IUser): string {
  return Math.round((new Date().valueOf() * Math.random())) + '';
};

const User = mongoose.model<IUser>('User', userSchema);

export default User;

2. 检查实例化与查询逻辑

  • 创建用户时必须通过虚拟字段password赋值:直接设置hashed_password和salt不会触发虚拟字段的setter,导致后续调用authenticate时字段缺失。正确写法:
    const newUser = new User({ password: 'your-password' });
    await newUser.save();
    
  • 查询用户时不能排除hashed_password和salt:如果查询语句用了select('-hashed_password -salt'),会导致从数据库取出的实例中这两个字段为undefined,验证自然失败。

3. 确保依赖版本兼容

Next.js 13.5建议搭配Mongoose 7.x及以上版本,对TypeScript的类型支持更完善。同时检查tsconfig.json的核心配置:

{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "types": ["mongoose"],
    "moduleResolution": "Node"
  }
}

内容的提问来源于stack exchange,提问作者Miguel Angel Marroquin Jordan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:12:42