Mongoose,如何强制执行 LeanDocument 类型?

问题描述 投票:0回答:2

在我们的代码库中,我们一直在使用

T.lean()
T.toObject()
,我们的返回类型将是
LeanDocument<T>
。 Mongoose 7 不再导出 LeanDocument,现有的迁移指南建议使用以下设置

// Do this instead, no `extends Document`
interface ITest {
  name?: string;
}
const Test = model<ITest>('Test', schema);

// If you need to access the hydrated document type, use the following code
type TestDocument = ReturnType<(typeof Test)['hydrate']>;

但这给了我

HydratedDocument
,我可以通过
HydratedDocument<T>
,这不是我想要的,因为它上面有所有文档方法。
作为替代方案,我可以仅使用
T
作为我的返回类型,但任何
Document<T>
都匹配
T

我想强制结果是 POJO,以防止文档从我们的 DAL 泄漏。

如何使用 typescript 和 mongoose 类型实现这一点?

typescript mongoose nestjs typescript-generics nestjs-mongoose
2个回答
2
投票

在猫鼬存储库中提出类似的问题,我决定采用以下方法:

// utils.ts
export type LeanDocument<T> = T & { $locals?: never };

所以在下面的情况下,typescript会提醒我无法返回文档:

async function getById(id: string): Promise<LeanDocument<User>> {
  const user = await UserModel.findById(id);
  return user;
  //       ^ Types of property '$locals' are incompatible.
}

我认为可以通过制作更清晰的类型错误来进一步改进,该错误将按照

Type error ... "You've forgot to convert to a lean document".
的方式进行说明,正如我之前在图书馆中看到的那样。
但我还没有找到如何做到这一点:)

编辑

一些打字稿魔法:

export type LeanDocument<T> = T & T extends { $locals: never }
  ? T
  : 'Please convert the document to a plain object via `.toObject()`';

会导致以下错误:

async function getById(id: string): Promise<LeanDocument<User>> {
  const user = await UserModel.findById(id);
  return user;
  //       ^ Type 'Document<unknown, any, User> & Omit<User & { _id: ObjectId; }, never>'
  // is not assignable to type 
  // '"Please convert the document to a plain object via `.toObject()`"'.ts(2322)
}

编辑2

使用条件类型的类型错误未按预期工作,我已尝试在这个问题中解决它。不幸的是,工作解决方案需要包装函数和断言。


0
投票

mongoose 8 中一般精益文档的返回类型是:

(mongoose.FlattenMaps<unknown> & Required<{ _id: unknown; }>) | null
© www.soinside.com 2019 - 2024. All rights reserved.