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

Mongoose 7中如何强制使用POJO类型替代LeanDocument?

解决方案

要在Mongoose 7中强制数据访问层(DAL)返回纯POJO(Plain Old JavaScript Object),避免泄漏带方法的HydratedDocument,可以通过以下几种TypeScript类型方案实现:

方法1:自定义POJO工具类型(递归清除函数属性)

创建一个递归工具类型,自动移除所有函数类型的属性,确保返回值仅包含数据字段:

type POJO<T> = {
  [K in keyof T as T[K] extends Function ? never : K]: 
    T[K] extends object ? POJO<T[K]> : T[K];
};

使用示例

在DAL函数中明确指定返回类型为POJO<你的业务接口>,TypeScript会自动校验返回值是否为纯数据对象:

interface ITest {
  name?: string;
  _id: string;
}

const Test = model<ITest>('Test', schema);

async function getTestById(id: string): Promise<POJO<ITest>> {
  // lean() 确保实际返回POJO,类型校验会拦截带方法的HydratedDocument
  return await Test.findById(id).lean();
}

如果不小心返回了未调用lean()的HydratedDocument,TypeScript会直接报错——因为文档对象包含save、remove等函数属性,不符合POJO类型约束。

方法2:直接复用Mongoose lean()的返回类型

Mongoose 7中调用lean()后,返回的类型本质上是业务接口加上Mongoose默认字段(如_id、__v)的纯对象类型,你可以直接通过ReturnType提取该类型:

// 提取单个文档lean()后的返回类型
type TestLeanDoc = Awaited<ReturnType<typeof Test.findByIdLean>>;

// 提取批量查询lean()后的返回类型
type TestLeanList = Awaited<ReturnType<typeof Test.findLean>>;

使用示例

async function getTestList(): Promise<TestLeanList> {
  return await Test.find({}).lean();
}

这种方式完全基于Mongoose内置类型,无需额外定义工具类型,类型匹配更精准。

方法3:扩展业务接口包含Mongoose默认字段

如果业务逻辑需要处理_id、__v等默认字段,可以直接在业务接口中声明这些字段,然后将其作为返回类型:

import { Types } from 'mongoose';

interface ITest {
  name?: string;
  _id: Types.ObjectId;
  __v?: number;
}

async function getTest(id: string): Promise<ITest> {
  return await Test.findById(id).lean() as ITest;
}

这种方式简单直接,适合需要明确处理Mongoose默认字段的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:55:25