In my project, I use Vue + TypeScript and Axios to get objects from the backend. So, I have an object type like this:
class Annoucement {
id!: string;
description?: string;
deal?: Deal;
realty?: Realty;
user?: User;
}
and a response like this:
{
"id": "guid",
"description": "string",
"deal": {
//...
},
"realty": {
//...
},
"user": {
//...
}
}
The main problem is that deal
and reality
can have different properties, thats why I cant just use something like this
let annoucement = new Annoucement();
annoucement.realty.floor = dto.realty.floor;
//...
EDIT: These are my classes
class Deal {
private _id!: string;
private _dealInfo!: Sell | Rent;
public get id(): string {
return this._id;
}
public set id(value: string) {
this._id = value;
}
public get dealInfo(): Sell | Rent {
return this._dealInfo;
}
public set dealInfo(value: Sell | Rent) {
this._dealInfo = value;
}
public constructor(id: string) {
this.id = id;
}
}
class Sell extends Deal {
public readonly dealType: string = "Sell";
private _conditions!: SellConditions;
public get conditions(): SellConditions {
return this._conditions;
}
public set conditions(value: SellConditions) {
this._conditions = value;
}
public constructor(id: string, conditions: SellConditions) {
super(id);
this.conditions = conditions;
}
}
class SellConditions {
private _id!: string;
public get id(): string {
return this._id;
}
public set id(value: string) {
this._id = value;
}
private _price!: number;
public get price(): number {
return this._price;
}
public set price(value: number) {
this._price = value;
}
private _type?: string | undefined;
public get type(): string | undefined {
return this._type;
}
public set type(value: string | undefined) {
this._type = value;
}
private _yearInOwn!: number;
public get yearInOwn(): number {
return this._yearInOwn;
}
public set yearInOwn(value: number) {
this._yearInOwn = value;
}
private _ownersCount!: number;
public get ownersCount(): number {
return this._ownersCount;
}
public set ownersCount(value: number) {
this._ownersCount = value;
}
private _prescribersCount!: number;
public get prescribersCount(): number {
return this._prescribersCount;
}
public set prescribersCount(value: number) {
this._prescribersCount = value;
}
private _haveChildOwners!: boolean;
public get haveChildOwners(): boolean {
return this._haveChildOwners;
}
public set haveChildOwners(value: boolean) {
this._haveChildOwners = value;
}
private _haveChildPrescribers!: boolean;
public get haveChildPrescribers(): boolean {
return this._haveChildPrescribers;
}
public set haveChildPrescribers(value: boolean) {
this._haveChildPrescribers = value;
}
}
class Rent extends Deal {
public readonly dealType: string = "Rell";
private _conditions!: RentConditions;
public get conditions(): RentConditions {
return this._conditions;
}
public set conditions(value: RentConditions) {
this._conditions = value;
}
public constructor(id: string, rentConditions: RentConditions) {
super(id);
this.conditions = rentConditions;
}
}
class RentConditions {
private _id!: string;
public get id(): string {
return this._id;
}
public set id(value: string) {
this._id = value;
}
private _price!: number;
public get price(): number {
return this._price;
}
public set price(value: number) {
this._price = value;
}
private _period?: string | undefined;
public get period(): string | undefined {
return this._period;
}
public set period(value: string | undefined) {
this._period = value;
}
private _deposit!: number;
public get deposit(): number {
return this._deposit;
}
public set deposit(value: number) {
this._deposit = value;
}
private _communalPays!: number;
public get communalPays(): number {
return this._communalPays;
}
public set communalPays(value: number) {
this._communalPays = value;
}
private _prepay!: number;
public get prepay(): number {
return this._prepay;
}
public set prepay(value: number) {
this._prepay = value;
}
private _facilities?: string | undefined;
public get facilities(): string | undefined {
return this._facilities;
}
public set facilities(value: string | undefined) {
this._facilities = value;
}
private _withKids!: boolean;
public get withKids(): boolean {
return this._withKids;
}
public set withKids(value: boolean) {
this._withKids = value;
}
private _withAnimals!: boolean;
public get withAnimals(): boolean {
return this._withAnimals;
}
public set withAnimals(value: boolean) {
this._withAnimals = value;
}
private _canSmoke!: boolean;
public get canSmoke(): boolean {
return this._canSmoke;
}
public set canSmoke(value: boolean) {
this._canSmoke = value;
}
}
class Reality {
private _id!: string;
public get id(): string {
return this._id;
}
public set id(value: string) {
this._id = value;
}
private _area!: number;
public get area(): number {
return this._area;
}
public set area(value: number) {
this._area = value;
}
private _type?: string | undefined;
public get type(): string | undefined {
return this._type;
}
public set type(value: string | undefined) {
this._type = value;
}
public constructor(id: string, area: number, type?: string | undefined) {
this.id = id;
this.area = area;
this.type = type;
}
}
class Office extends CommercialBuilding {
private _name?: string | undefined;
public get name(): string | undefined {
return this._name;
}
public set name(value: string | undefined) {
this._name = value;
}
private _roomsCount!: number;
public get roomsCount(): number {
return this._roomsCount;
}
public set roomsCount(value: number) {
this._roomsCount = value;
}
}
class CommercialBuilding extends Reality {
private _floorsCount!: number;
public get floorsCount(): number {
return this._floorsCount;
}
public set floorsCount(value: number) {
this._floorsCount = value;
}
private _entry!: boolean;
public get entry(): boolean {
return this._entry;
}
public set entry(value: boolean) {
this._entry = value;
}
private _adress!: string;
public get adress(): string {
return this._adress;
}
public set adress(value: string) {
this._adress = value;
}
private _isUse!: boolean;
public get isUse(): boolean {
return this._isUse;
}
public set isUse(value: boolean) {
this._isUse = value;
}
private _isAcces!: boolean;
public get isAcces(): boolean {
return this._isAcces;
}
public set isAcces(value: boolean) {
this._isAcces = value;
}
private _building?: Building | undefined;
public get building(): Building | undefined {
return this._building;
}
public set building(value: Building | undefined) {
this._building = value;
}
class Building {
private _id!: string;
public get id(): string {
return this._id;
}
public set id(value: string) {
this._id = value;
}
private _class!: string;
public get classBuilding(): string {
return this._class;
}
public set classBuilding(value: string) {
this._class = value;
}
private _buildingYear!: number;
public get buildingYear(): number {
return this._buildingYear;
}
public set buildingYear(value: number) {
this._buildingYear = value;
}
private _centerName?: string | undefined;
public get centerName(): string | undefined {
return this._centerName;
}
public set centerName(value: string | undefined) {
this._centerName = value;
}
private _haveParking!: boolean;
public get haveParking(): boolean {
return this._haveParking;
}
public set haveParking(value: boolean) {
this._haveParking = value;
}
private _isEquipment!: boolean;
public get isEquipment(): boolean {
return this._isEquipment;
}
public set isEquipment(value: boolean) {
this._isEquipment = value;
}
}
Class diagram that demonstrates an inheritance hierarchy
As you can see, when i want to retrieve some announcements from the db, i can get different types of realty. I have no idea which way is the best to map response to an entity.
So I have just two solution of this problem:
if
and define typeI have tried to find a solution in Google. But in most cases, people ask how to map an entity to a DTO.
I would add a type of realty (some kind of enum maybe?) to response and use a switch statement
switch(response.type) {
case realty1: {
MapRealty1(r);
break;
}
case realty2: {
MapRealty2();
break;
}
default: {
throw new Error('Unsupported realty type');
break;
}
}
There is no way your code will guess what is the type from nowhere - you need to provide this information somehow, since your your frontend doesn't now you backend classes this is imo the best way to tell it