使用Next.js、Typegoose、Mongoose遇TypeError:instanceof右侧非对象
解决Typegoose调用
getModelForClass时的"Right-hand side of 'instanceof' is not an object"错误 错误根源分析
你的代码里有两个关键问题触发了这个错误:
- 装饰器提前引用未定义的类:
@post<UserClass>装饰器在UserClass类定义完成前就将其作为泛型参数使用,此时UserClass未完成初始化,导致Typegoose内部类型检查逻辑出错。 - 非法修改
_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
相关产品推荐
相关产品推荐

