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

使用Next.js、Typegoose、Mongoose遇TypeError:instanceof右侧非对象

解决Typegoose调用getModelForClass时的"Right-hand side of 'instanceof' is not an object"错误

错误根源分析

你的代码里有两个关键问题触发了这个错误:

  1. 装饰器提前引用未定义的类:@post<UserClass>装饰器在UserClass类定义完成前就将其作为泛型参数使用,此时UserClass未完成初始化,导致Typegoose内部类型检查逻辑出错。
  2. 非法修改_id类型:在post钩子中把doc._id从ObjectId强制替换为字符串,破坏了Mongoose对_id的类型约定,导致内部执行instanceof检查时,右侧的类型对象失效。

修复方案

1. 移除手动修改_id的逻辑

Mongoose默认会为文档生成id虚拟属性(自动将_id转为字符串),完全不需要手动赋值或替换_id。删除两个post钩子中修改_id的代码:

@post<UserClass>('save', function (doc) {
  // 移除手动修改_id和id的代码
})
@post<UserClass[]>(/^find/, function (docs) {
  // @ts-ignore
  if (this.op === 'find') {
    // 移除手动修改_id和id的代码
  }
})

如果需要自定义id属性,改用虚拟属性实现:

class UserClass {
  // ...其他属性
  @prop({ virtual: true })
  get id(): string {
    return this._id.toString();
  }
}

2. 修正装饰器的泛型引用

将post装饰器的泛型参数改为typeof UserClass,避免引用未初始化的类:

@post<typeof UserClass>('save', function (doc) {
  // 这里doc的类型会自动推断为UserClass实例
})
@post<typeof UserClass>(/^find/, function (docs) {
  // @ts-ignore
  if (this.op === 'find') {
    // docs的类型会自动推断为UserClass实例数组
  }
})

3. 完整修复后的代码

import { ModelOptions, Severity, getModelForClass, index, post, prop } from '@typegoose/typegoose';
import mongoose from 'mongoose';

@post<typeof UserClass>('save', function (doc) {
  // 可添加其他save后逻辑,无需修改_id
})
@post<typeof UserClass>(/^find/, function (docs) {
  // @ts-ignore
  if (this.op === 'find') {
    // 可添加其他find后逻辑,无需修改_id
  }
})
@ModelOptions({
  schemaOptions: {
    timestamps: true,
    collection: 'users',
  },
  options: {
    allowMixed: Severity.ALLOW,
  },
})
@index({ username: 1 })
class UserClass {
  @prop({ required: true, unique: true })
  public username: string;

  @prop({ required: true })
  public firstName: string;

  @prop({ required: true })
  public lastName: string;

  @prop({ required: true })
  public hash: string;
  
  @prop({ virtual: true })
  get id(): string {
    return this._id.toString();
  }

  _id: mongoose.Types.ObjectId;
}
export const User = getModelForClass(UserClass);

额外注意事项

  • 确保Typegoose与Mongoose版本兼容:不同版本的Typegoose对Mongoose的依赖有严格要求,比如Typegoose v12需要搭配Mongoose v7+。
  • 禁止手动修改Mongoose内置的_id字段:这会破坏内部数据结构和类型检查,引发不可预见的错误。

内容的提问来源于stack exchange,提问作者NewbieCoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:11:26