классовая трансформация дискриминируемых - PullRequest
0 голосов
/ 26 апреля 2020

Я играл с routing-controllers, и это встроенная способность преобразования класса. Я попытался создать интерфейс, в котором я мог бы выполнить поисковый запрос на основе location id или location coordinate. Поэтому я намеревался использовать дискриминируемый союз в качестве параметра тела и не мог заставить его работать. (См. Последний вывод консоли, что я имею в виду под «не работает»)

Как пример:

interface LocationCoordinates {
    type: 'coordinate'
    longitude: number
    latitude: number
}

interface LocationId {
    type: 'id'
    id: number
}

class LocationRadius {
    data: LocationCoordinates | LocationId
    searchRadiusInKm: number
}

// raw input for LocationCoordinates
const rawLocationCoordinates = {
    data: {
        longitude: 22,
        latitude: 33
    },
    searchRadiusInKm: 30
}


// raw input for LocationId
const rawLocationId = {
    data: {
        id: 1
    },
    searchRadiusInKm: 30
}
// transfrom both raw inputs
const realLocationCoordinates = plainToClass(LocationRadius, rawLocationCoordinates);
const realLocationId = plainToClass(LocationRadius, rawLocationId);


console.log({
    coordinateType: realLocationCoordinates.data.type, // expect 'coordinate' but got 'undefinded'
    idType: realLocationId.data.type // expect 'id' but got 'undefinded'
});

Есть ли способ добиться этого?

1 Ответ

1 голос
/ 26 апреля 2020

Вы можете сделать это, но вам потребуются некоторые изменения:

  1. LocationId и LocationCoordinates должны быть классами
  2. Вы должны добавить декоратор @Type к входное свойство. Это позволяет class-transformer обрабатывать десериализацию на основе заданного c параметра дискриминатора
class LocationRadius {
 @Type(() => Object, {
     keepDiscriminatorProperty: true,
     discriminator: {
         property: "type",
         subTypes: [
             { value: LocationCoordinates, name: "coordinate" },
             { value: LocationId, name: "id" }
         ]
     }
 })
 data: LocationCoordinates | LocationId
 searchRadiusInKm: number
}
Вы должны добавить свойство type к вашему входу, чтобы позволить даже TS различать объединение:
 // raw input for LocationCoordinates
const rawLocationCoordinates = {
   data: {
       type: "coordinate",
       longitude: 22,
       latitude: 33
   },
   searchRadiusInKm: 30
}

Вы можете увидеть результат в этом StackBlitz Проект Я настроил

...