Typescript中Mongoose双Model联合类型findOne签名不兼容问题
解决TypeScript联合类型下Mongoose Model.findOne的签名冲突问题
问题原因
TypeScript对联合类型的函数调用有严格约束:调用联合类型的函数时,传入的参数必须能同时满足所有联合成员的函数签名。由于ModelA.findOne要求FilterQuery<InterfaceA>类型参数,ModelB.findOne要求FilterQuery<InterfaceB>类型参数,即使你传入any类型的query,TS依然会判定两个签名互不兼容,从而报错。
方案1:泛型约束(类型安全且优雅)
通过泛型将Model与对应的文档接口绑定,让TS自动推断匹配的参数和返回值类型,从根源上避免签名冲突:
import { Model, FilterQuery, Document } from 'mongoose'; // 假设你的文档接口定义如下 interface InterfaceA { _id: string; createdAt: Date; propA: string; // A独有的属性 } interface InterfaceB { _id: string; createdAt: Date; propB: number; // B独有的属性 } async function foo<T extends InterfaceA | InterfaceB>( model: Model<T>, query: FilterQuery<T> ) { const res = await model.findOne(query); // res的类型自动推断为 Document<T> | null,即最终的 Document<InterfaceA> | Document<InterfaceB> | null console.log(res); }
方案2:类型断言(快速解决)
如果不需要严格的类型检查,直接用类型断言告知TS忽略签名冲突,这是最简洁的临时解决方案:
async function foo(model: ModelA | ModelB, query: any) { const res = await (model as ModelA).findOne(query) as Document<InterfaceA> | Document<InterfaceB>; console.log(res); }
方案3:扩展联合类型签名
通过扩展联合类型,给Model补充一个兼容的findOne签名,让TS认可跨Model的调用:
import { Document } from 'mongoose'; type CompatibleModel = ModelA | ModelB & { findOne(query: any): Promise<Document<InterfaceA> | Document<InterfaceB>>; }; async function foo(model: CompatibleModel, query: any) { const res = await model.findOne(query); console.log(res); }
内容的提问来源于stack exchange,提问作者hkonsti
相关产品推荐
相关产品推荐

