class歧视工会改造

class transformation of discriminated unions

我玩过 routing-controllers,它是 build-in class-transformer 能力。我试图构建一个界面,我可以在其中执行基于 location idlocation coordinate 的搜索查询。因此,我打算将 discriminated union 用作 body 参数,但无法使其正常工作。 (请参阅最后一个控制台输出 'not working' 的意思)

举个例子:

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. LocationIdLocationCoordinates 应该是 类
  2. 您应该向输入 属性 添加一个 @Type 装饰器。这允许 class-transformer 处理基于特定鉴别器参数的反序列化
class LocationRadius {
 @Type(() => Object, {
     keepDiscriminatorProperty: true,
     discriminator: {
         property: "type",
         subTypes: [
             { value: LocationCoordinates, name: "coordinate" },
             { value: LocationId, name: "id" }
         ]
     }
 })
 data: LocationCoordinates | LocationId
 searchRadiusInKm: number
}
  1. 您应该在您的输入中添加一个 type 属性,以允许甚至 TS 区分并集:
 // raw input for LocationCoordinates
const rawLocationCoordinates = {
   data: {
       type: "coordinate",
       longitude: 22,
       latitude: 33
   },
   searchRadiusInKm: 30
}

你可以在这个StackBlitz project看到结果我设置了