扩展Mongoose查询缓存功能:JS转TS遇类型错误求助
Mongoose Query缓存扩展的TypeScript错误修复
错误1:All declarations of 'Query' must have identical type parameters.
Mongoose原生Query接口包含多个泛型参数,自定义扩展时必须与原接口的泛型签名完全匹配,不能仅声明单个泛型参数。
修复方式:扩展Query接口时使用完整的泛型参数列表,返回类型用this保持链式调用的泛型一致性:
declare module 'mongoose' { interface Query<ResultType, DocType, THelpers = {}, RawDocType = DocType, QueryOp = "find", DocTypeFields = Required<DocType>> { useCache?: boolean; hashKey?: string; cache(options?: { key?: unknown }): this; } }
错误2:Argument of type 'IArguments' is not assignable to parameter of type '[]'
TypeScript对arguments对象的类型检查严格,直接传递会触发类型不匹配报错。可以改用剩余参数接收exec的入参,替代arguments。
修复方式:在exec方法定义中使用剩余参数,调用原生exec时直接传递该参数数组:
Query.prototype.exec = async function (...args: Parameters<typeof exec>): Promise<any> { if (!this.useCache) { return exec.apply(this, args); } // 后续代码中统一用args代替arguments }
错误3:Property 'mongooseCollection' does not exist on type 'Query<...>'
mongooseCollection是Mongoose内部未对外暴露的属性,TypeScript类型定义中未包含该字段。可以通过公开的this.model.collection.name获取集合名称。
修复方式:替换原集合名称获取代码:
const key = JSON.stringify(Object.assign({}, this.getFilter(), { collection: this.model.collection.name, }));
完整修复后的TypeScript代码
import mongoose, { Query } from 'mongoose'; import RedisClient from './redisClient'; // 扩展Mongoose Query接口,匹配完整泛型参数 declare module 'mongoose' { interface Query<ResultType, DocType, THelpers = {}, RawDocType = DocType, QueryOp = "find", DocTypeFields = Required<DocType>> { useCache?: boolean; hashKey?: string; cache(options?: { key?: unknown }): this; } } const exec = Query.prototype.exec; // 实现cache方法,返回this保持链式调用 Query.prototype.cache = function (options = {}): this { this.useCache = true; this.hashKey = JSON.stringify(options.key || ''); return this; }; // 重写exec方法,使用剩余参数避免arguments类型问题 Query.prototype.exec = async function (...args: Parameters<typeof exec>): Promise<any> { if (!this.useCache) { return exec.apply(this, args); } const key = JSON.stringify(Object.assign({}, this.getFilter(), { collection: this.model.collection.name, })); const cachedValue = await RedisClient.getHCache(this.hashKey, key); if (cachedValue) { const doc = JSON.parse(cachedValue); return Array.isArray(doc) ? doc.map((d: any) => new this.model(d)) : new this.model(doc); } const result = await exec.apply(this, args); await RedisClient.setHCache(this.hashKey, key, JSON.stringify(result)); return result; };
内容的提问来源于stack exchange,提问作者dayo
相关产品推荐
相关产品推荐

