在我的 NestJS 应用程序中,在我的 Mongoose 模式之一中,我在数组中嵌入了鉴别器。当迭代数组并尝试访问特定于一个鉴别器的字段时,由于某种原因该字段未定义。
这里可以参考 NestJS 文档,了解如何处理鉴别器。
@Schema()
export class User {
@Prop({ required: true, type: [BaseAction] })
subscriptionHistory: BaseAction[];
}
export const UserSchema = SchemaFactory.createForClass(User);
export type UserModel = Model<User>;
export type UserDocument = HydratedDocument<User>;
@Schema({ _id: false, discriminatorKey: 'action', autoCreate: false })
export class BaseAction {
@Prop({ required: true, type: String, enum: SubscriptionAction })
action: string;
@Prop({ default: Date.now })
timestamp: Date;
}
export const BaseActionSchema = SchemaFactory.createForClass(BaseAction);
@Schema({ _id: false })
export class UpgradeAction {
action: string = SubscriptionAction.Upgrade;
timestamp: Date;
@Prop({ required: true, type: Object })
details: SubscriptionChange & StartDateChange & EndDateChange;
}
export const UpgradeActionSchema = SchemaFactory.createForClass(UpgradeAction);
/*
* Here exemplary the SubscriptionChange helper used in the 'details' prop
*/
@Schema({ _id: false })
class SubscriptionChange {
@Prop({ required: true })
oldVersion: number;
/* Some more properties */
}
@Module({
imports: [
MongooseModule.forFeature([
{ name: User.name, schema: UserSchema },
{
name: BaseAction.name,
schema: UserSchema.path('subscriptionHistory').schema,
discriminators: [
{ name: SubscriptionAction.Upgrade, schema: UpgradeActionSchema },
/* further discriminators here */
],
},
])
],
/* controllers, providers, exports */
})
export class UserModule {}
在我的一项服务中,我从数据库中检索用户并迭代 subscriptionHistory 数组。我检查操作类型,然后想要读取操作的
details
属性。
在调试中运行时,我可以看到详细信息字段在内存中,但每当我访问它时,它都是未定义的。
export class SomeService {
async someHandler(userId) {
const user = await this.userService.getUserById(userId); // works fine
const action = user.subscriptionHistory.find((h) => {
if (h.action === SubscriptionAction.Upgrade) { // works fine
console.log(h) // <-- 'details' is being printed
const { details } = h as UpgradeAction // I have to cast to be able to extract details
return details.oldVersion > 1; // This throws
}
});
}
}
抛出的错误是:
无法读取未定义的属性(读取“oldVersion”)
在调试器中,我可以看到
h
的类型为 EmbeddedDocument
并且 details
存在,但无法访问。
我相信,这个问题与我没有正确键入转换有关。不幸的是,我不知道如何解决这个问题。我如何访问
details
?
目前,我找到了一个非常丑陋的解决方案。它有效,但绝对不是解决这个问题的正确方法。如果有人知道更好的解决方案,我非常感谢进一步的建议。
export class SomeService {
async someHandler(userId) {
const user = await this.userService.getUserById(userId);
const action = user.subscriptionHistory.find((h) => {
if (h.action === SubscriptionAction.Upgrade) {
// @ts-ignore
const { details } = h._doc as UpgradeAction;
return details.oldVersion > 1;
}
// @ts-ignore
})._doc as UpgradeAction;;
}
}
我直接访问 EmbeddedDocument 的 _doc 属性并将其转换为正确的操作类型。由于 _doc 实际上是不可见的,所以我必须忽略打字稿错误。