I am unable to access properties of a nested loaded entities. I have the following structure
Treatment OneToMany TreatmentCycle
TreatmentCycle ManyToOne Physician
Physician ManyToOne User
User ManyToOne Country
I need to map this to another view model for presenting but I am unable to map treatmentCycle->physician->user
properties
Code:
const treatment = await this.em.findOne(Treatment, id, {
populate: [
"diagnosis",
"physician",
"physician.user",
"country",
"medication",
"treatmentCycles",
"treatmentCycles.physician",
"treatmentCycles.physician.user",
"treatmentCycles.physician.user.country",
"treatmentCycles.physician.profession",
"treatmentCycles.physician.hospital",
"treatmentCycles.medicationRegimen",
"treatmentInterruptions",
],
});
When trying to map here result the following TS2339: Property user does not exist on type { id: string; } & Reference<Physician>
although I loaded in the relation previously. Same error applies for the hospital
and profession
this.treatmentCycles = treatment.treatmentCycles.getItems().map((cycle) => {
return {
physician: {
id: cycle.physician.id,
userId: cycle.physician.user.id,
fullName: `${cycle.physician.user.firstName} ${cycle.physician.user.lastName}`,
email: cycle.physician.user.email,
profession: cycle.physician.profession.identifier,
hospitalIdentifier: cycle.physician.hospital.identifier,
country: {
id: cycle.physician.user.country.id,
code: cycle.physician.user.country.$.code,
name: cycle.physician.user.country.name,
},
},
};
});
Am I missing something here or is there another way to do it?
EDIT
Entity definition for Treatment
@Entity({
tableName: "treatment",
repository: () => TreatmentRepository,
})
export default class Treatment extends AggregateRoot<Treatment, "id"> {
[EntityRepositoryType]?: TreatmentRepository;
@ManyToOne(() => Country, { ref: true })
country!: Ref<Country>;
@Enum({
items: () => AvailableTreatmentStatuses,
array: false,
default: [AvailableTreatmentStatuses.ONGOING],
})
status!: AvailableTreatmentStatuses;
@Property({
type: "date",
nullable: false,
fieldName: "start_date",
})
startDate!: Date;
@Property({
type: "date",
nullable: true,
default: null,
fieldName: "end_date",
})
endDate: Date | null = null;
@Enum({
items: () => AvailableTreatmentEndReason,
array: false,
default: null,
nullable: true,
fieldName: "end_reason",
})
reasonEnded: AvailableTreatmentEndReason | null = null;
@ManyToOne(() => Diagnosis, { ref: true })
diagnosis!: Ref<Diagnosis>;
@ManyToOne(() => Medication, { ref: true })
medication!: Ref<Medication>;
@ManyToOne(() => Physician, { ref: true })
physician!: Ref<Physician>;
@OneToMany(() => TreatmentCycle, (treatmentCycle) => treatmentCycle.treatment)
treatmentCycles = new Collection<TreatmentCycle>(this);
@OneToMany(
() => TreatmentInterruption,
(treatmentInterruption) => treatmentInterruption.treatment
)
treatmentInterruptions = new Collection<TreatmentInterruption>(this);
@Property({ persist: false })
prescriptionsCount!: number;
@Property({ persist: false })
interruptionsCount!: number;
constructor(payload: {
countryId: string;
status: AvailableTreatmentStatuses;
startDate: Date;
endDate?: Date | null;
endReason?: AvailableTreatmentEndReason | null;
diagnosisId: string;
medicationId: string;
physicianId: string;
}) {
super();
if (payload.endReason && !payload.endDate) {
throw new UnableToCreateNewTreatmentException(
"Cannot add ended treatment without an end date"
);
}
if (!payload.endReason && payload.endDate) {
throw new UnableToCreateNewTreatmentException(
"Cannot add ended treatment without an end reason"
);
}
this.status = payload.status;
this.startDate = payload.startDate;
this.endDate = payload.endDate;
this.reasonEnded = payload.endReason;
this.country = Reference.createFromPK(Country, payload.countryId);
this.diagnosis = Reference.createFromPK(Diagnosis, payload.diagnosisId);
this.medication = Reference.createFromPK(Medication, payload.medicationId);
this.physician = Reference.createFromPK(Physician, payload.physicianId);
}
}
Since you are using the Reference
wrapper (Ref
type), your relations are mapped to it instead of the underlying entity. This means that to access them, you need to use one of the ways to access the wrapped entity. There are several ways to do it:
$
symbol-cycle.physician.user.firstName
+cycle.physician.$.user.$.firstName
Reference.load()
which is async and ensures the relation is loaded-cycle.physician.user.firstName
+(await (await cycle.physician.load()).user.load()).firstName
Loaded
type), you can use Reference.unwrap()
which is sync and only gives you the underlying entity without checking its loaded state.-cycle.physician.user.firstName
+cycle.physician.unwrap().user.unwrap().firstName
https://mikro-orm.io/docs/next/guide/type-safety#reference-wrapper