在我们的代码库中,我们一直在使用
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 类型实现这一点?
在猫鼬存储库中提出类似的问题,我决定采用以下方法:
// 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)
}
使用条件类型的类型错误未按预期工作,我已尝试在这个问题中解决它。不幸的是,工作解决方案需要包装函数和断言。
mongoose 8 中一般精益文档的返回类型是:
(mongoose.FlattenMaps<unknown> & Required<{ _id: unknown; }>) | null