Как я могу сопоставить DTO с объектом в машинописном тексте?

В своем проекте я использую Vue + TypeScript и Axios для получения объектов из бэкенда. Итак, у меня есть такой тип объекта:

class Annoucement {
    id!: string;
    description?: string;
    deal?: Deal;
    realty?: Realty;
    user?: User; 
}

и такой ответ:

{
  "id": "guid",
  "description": "string",
  "deal": {
     //...
  },
  "realty": {
     //...
  },
  "user": {
     //...
  }
}

Основная проблема в том, что deal и reality могут иметь разные свойства, поэтому я не могу просто использовать что-то вроде этого.

let annoucement = new Annoucement();
annoucement.realty.floor = dto.realty.floor;
//...

Обновлено: Это мои занятия

    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;
        }
    }

Диаграмма классов, демонстрирующая иерархию наследования.

Как видите, когда я хочу получить некоторые объявления из базы данных, я могу получить разные типы недвижимости. Я понятия не имею, какой способ лучше всего сопоставить ответ сущности.

Итак, у меня есть только два решения этой проблемы:

  1. Проверьте свойства ответов с помощью if и определите тип.
  2. Получайте ответы в разных функциях, где я буду знать структуру ответа.

Я попытался найти решение в Google. Но в большинстве случаев люди спрашивают, как сопоставить сущность с DTO.

Используйте реактивные расширения (RxJS) rxjs.dev/guide/overview

Art Bindu 16.05.2024 20:10

Проблема здесь не ясна. Вы получаете ошибку? Вы говорите: «Основная проблема в том, что deal и reality могут иметь разные свойства», но приведенный вами после этого пример кода, который, как вы говорите, не работает, вообще не упоминает deal. Пожалуйста, отредактируйте свой вопрос, включив в него минимально воспроизводимый пример . Это повысит вероятность того, что вы получите ответ. Когда я попробовал сделать пример на основе вашего кода tsplay.dev/mqg0dw многого не хватало, и я не смог увидеть ту же проблему, которую вы описываете.

Alex Wayne 16.05.2024 21:35
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
2
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я бы добавил тип недвижимости (может быть, какое-то перечисление?) в ответ и использовал оператор переключения.

switch(response.type) { 
   case realty1: { 
      MapRealty1(r); 
      break; 
   } 
   case realty2: { 
      MapRealty2(); 
      break; 
   } 
   default: { 
      throw new Error('Unsupported realty type'); 
      break; 
   } 
} 

Ваш код не сможет угадать тип из ниоткуда - вам нужно каким-то образом предоставить эту информацию, поскольку ваш интерфейс теперь не знает классов бэкэнда, это, по моему мнению, лучший способ сообщить об этом.

Другие вопросы по теме