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:$
symbolReference.load()
which is async and ensures the relation is loadedLoaded
type), you can useReference.unwrap()
which is sync and only gives you the underlying entity without checking its loaded state.https://mikro-orm.io/docs/next/guide/type-safety#reference-wrapper