NestJS泛型CRUD服务中Mongoose update方法changes参数类型定义问题
解决方案
你遇到的类型报错核心原因是Mongoose的findOneAndUpdate方法第二个参数不接受完整的模型类型T,它既支持直接传入部分字段对象做覆盖更新,也支持传入带$set/$inc等操作符的更新对象,Mongoose已经封装了专用的泛型类型UpdateQuery来匹配这个参数的类型规则。
修改后的完整代码
import { Injectable, InternalServerErrorException } from '@nestjs/common'; import { Document, FilterQuery, Model, UpdateQuery } from 'mongoose'; @Injectable() export abstract class GenericCrudService<T extends Document> { constructor(private readonly model: Model<T>) {} async findAll( conditions: FilterQuery<T>, projection: string | Record<string, unknown> = {}, options: Record<string, unknown> = {}, ): Promise<T[]> { try { return await this.model.find( conditions, projection, options, ); } catch (err) { console.log('generic error: ' + err); throw new InternalServerErrorException(); } } async updateOne( conditions: FilterQuery<T>, changes: UpdateQuery<T>, options: Record<string, unknown> = { new: true }, ): Promise<T | null> { try { return await this.model.findOneAndUpdate( conditions, changes, options ); } catch (err) { console.log('generic service error: ' + err); throw new InternalServerErrorException(); } } }
关键修改说明
- 新增导入Mongoose内置的
UpdateQuery泛型类型,将changes参数的类型从any替换为UpdateQuery<T>,完美兼容直接传部分字段、传带更新操作符的对象两种场景,不会再报类型错误。如果你的业务只允许传入实体的部分字段更新,不允许使用Mongoose操作符,也可以将类型替换为Partial<T> - 将原有的
conditions参数类型从Partial<Record<keyof T, unknown>>直接替换为Mongoose内置的FilterQuery<T>,省去类型强制转换的步骤,类型覆盖更全面,支持$or/$gt等高级查询操作符 - 修正返回值类型为
Promise<T | null>,匹配findOneAndUpdate未命中查询条件时返回null的原生行为,避免类型安全隐患 - 新增默认
options配置{ new: true },默认返回更新后的文档,符合业务开发的常见需求,不需要可自行移除
内容的提问来源于stack exchange,提问作者Alessandro Rhomberg
相关产品推荐
相关产品推荐

