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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:18:03