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

TypeScript编译Mongoose查询助手报错:find方法异常findOne正常

Mongoose查询助手在TypeScript中.find()报错问题排查

问题现象

开发TypeScript+Mongoose项目时,自定义查询助手后,.findOne().byKey("123")可正常编译,但.find().byKey("123")会触发TypeScript类型错误,核心矛盾是this上下文的返回类型不兼容(数组类型 vs 单个文档类型)。

代码示例

import { InferRawDocType, Schema, model } from "mongoose";

export const mySchemaDefinition = {
  key: "string",
  value: "string"
} as const;
export type RawSchema = InferRawDocType<typeof mySchemaDefinition>;
export const mySchema = new Schema(mySchemaDefinition, {
  query: {
    byKey: function (key: string) {
      return this.where({ key: key });
    }
  }
});
export const MyModel = model("MyModel", mySchema);

MyModel.find({ key: "123" }).exec(); // 正常
MyModel.findOne().byKey("123").exec(); // 正常
MyModel.find().byKey("123").exec(); // 报错

错误信息

The 'this' context of type 'QueryWithHelpers<(Document<unknown, { byKey: <T extends Query<unknown, Document<unknown, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>> & FlatRecord<{ readonly key: "string"; readonly value: "string"; }> & { _id: ObjectId; } & { __v: number; }, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>, "find", Record<string, never>>>(this: T, key: string) => T; }, { readonly key: "string"; readonly value: "string"; }> & { readonly key: "string"; readonly value: "string"; 
} & { _id: ObjectId; } & { __v: number; })[], Document<unknown, { byKey: <T extends Query<unknown, Document<unknown, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>> & FlatRecord<{ readonly key: "string"; readonly value: "string"; }> & { _id: ObjectId; } & { __v: number; }, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>, "find", Record<string, never>>>(this: T, key: string) => T; }, { readonly key: "string"; readonly value: "string"; }> & { readonly key: "string"; readonly value: "string"; } & { _id: ObjectId; } & { __v: number; }, { byKey: <T extends Query<unknown, Document<unknown, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>> & FlatRecord<{ readonly key: "string"; readonly value: "string"; }> & { _id: ObjectId; } & { __v: number; }, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>, "find", Record<string, never>>>(this: T, key: string) => T; }, { readonly key: "string"; readonly value: "string"; }, "find", {}>' is not assignable to method's 'this' of type 'Query<unknown, Document<unknown, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; 
}>> & FlatRecord<{ readonly key: "string"; readonly value: "string"; }> & { _id: ObjectId; } & { __v: number; }, {}, FlatRecord<{ readonly key: "string"; readonly value: "string"; }>, "find", Record<string, never>>'.
  The types returned by 'lean(...).exec()' are incompatible between these types.
    Type 'Promise<({ readonly key: "string"; readonly value: "string"; } & { _id: ObjectId; } & { __v: number; })[]>' is not assignable to type 'Promise<{ readonly key: "string"; readonly value: "string"; } & { _id: ObjectId; } & { __v: number; }>'.
      Type '({ readonly key: "string"; readonly value: "string"; } & { _id: ObjectId; } & { __v: number; })[]' is not assignable to type '{ readonly key: "string"; readonly value: "string"; } & 
{ _id: ObjectId; } & { __v: number; }'.
        Type '({ readonly key: "string"; readonly value: "string"; } & { _id: ObjectId; } & { __v: number; })[]' is missing the following properties from type '{ readonly key: "string"; readonly value: "string"; }': key, value

环境配置

  • 编译命令:
tsc index.ts --esModuleInterop --outDir ./build --noErrorTruncation
  • tsconfig.json(项目包含React应用):
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}

问题原因与解决方案

原因

这是Mongoose类型定义的兼容性问题:.find()返回的Query对象泛型参数是数组类型,而.findOne()是单个文档类型。查询助手默认的类型推断没有正确区分这两种场景,导致this上下文的返回类型不匹配,触发TypeScript类型检查错误。你的tsconfig配置无问题,.findOne()正常运行可佐证这一点。

解决方案

  1. 显式指定查询助手泛型类型
    修改查询助手定义,让它适配任意Query类型,兼容数组和单个文档场景:
import { Query } from "mongoose";

export const mySchema = new Schema(mySchemaDefinition, {
  query: {
    byKey: function<T>(this: Query<T, RawSchema>, key: string) {
      return this.where({ key });
    }
  }
});
  1. 临时使用类型断言
    若不想修改查询助手定义,可在调用时用类型断言跳过检查:
(MyModel.find() as typeof MyModel.findOne()).byKey("123").exec();
  1. 升级Mongoose版本
    该类型问题在Mongoose 6.x及以上稳定版本中已修复,升级到最新版可直接解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:25:57