bounty还有4天到期。此问题的答案有资格获得+50声望奖励。EcksDy希望引起更多注意这个问题:答案应该包括问题的解决方案,最好是解释类型系统的行为。
我尝试创建一个PojoDocument<T>
泛型类型,以防止mongoose文档从DAL中泄漏。
我的目标是确保返回的对象不是mongoose Document
,而是POJO(PojoDocument
)。
我通过检查T
永远不能有$locals
属性来做到这一点,因为它在所有文档中都可以找到:
// If `T` has `$locals` property, then resolve the string as the type, which will clash with `T` and show as an error.
// So when `$locals` property not found, `T` will be returned as the type.
export type PojoDocument<T> = T & T extends { $locals?: never }
? T
: 'Please convert the document to a POJO via `.toObject()` or .lean()`';
我的类型用法如下:
class A {
...
async create(dto: CreateUserDto): Promise<PojoDocument<User>> {
const result = await this.userModel.create(dto);
return result.toObject();
// ^ Type 'LeanDocument<User & Document<any, any, User>>' is not assignable to type '"Please convert the document to a POJO via `.toObject()` or .lean()`"'.
}
}
LeanDocument<User & Document<any, any, User>>
类型等于:
interface ResultToObjectType {
__v?: any;
_id?: any;
name: string;
}
此外,当我检查create
方法在使用它的地方返回的内容时,我得到了以下结果:
Promise<"Please convert the document to a POJO via `.toObject()` or .lean()`">
这意味着PojoDocument<T>
默认为“else”条件,而不是为其提供的T
。
我尝试修改类型以包含__v
和_id
,认为这就是它不认为该类型被$locals?: never
扩展的原因,因为这些属性在T
上不存在,但它没有改变任何东西:
export type PojoDocument<T> = T extends { $locals?: never; __v?: any; _id?: any }
? T
: 'Please convert the document to a POJO via `.toObject()` or .lean()`';
有什么想法可以实现这种检查?
编辑#1
我加了一个小型的游戏场。
1条答案
按热度按时间q3aa05251#
问题实际上是
UsersDal.create
,其中返回类型为:User
只有name
,不符合PojoDocument
的要求,返回字符串错误:然而,
pojoResult
确实遵守PojoDocument
的条件,显然,它不是函数期望返回的字符串。总结问题:
您的
create
期望返回一个文本字符串的promise,而不是promise对象。我不熟悉
mongoose
,但我可以建议将create
的返回类型更改为:完整代码:
Playground