class-validator 验证联合类型

class-validator validate union type

我有一个mongoose discriminator schema,这意味着数据会根据其中一个属性而有所不同。

class Feature {
  name: string
  option: ColorFeature|SizeFeature
}

class ColorFeature {
  kind: 'color'
  color: string
}

class SizeFeature {
  kind: 'size'
  size: number
}

验证 Feature class 使其只接受 2 种不同类型的正确方法是什么?

可以通过validateNested()class-transformer discriminator

一起使用来实现
class BaseFeature {
  kind: 'size' | 'color'
}

class ColorFeature extends BaseFeature {
  kind: 'color'
  color: string
}

class SizeFeature extends BaseFeature {
  kind: 'size'
  size: number
}


class Feature {
  name: string

  @ValidateNested()
  @Type(() => BaseFeature, {
    keepDiscriminatorProperty: true,
    discriminator: {
      property: 'kind',
      subTypes: [
        { value: SizeFeature, name: 'size' },
        { value: ColorFeature, name: 'color' },
      ],
    },
  })
  option: SizeFeature | ColorFeature;
}

我为此花了很多时间,我终于找到了比当前答案更简洁的方法。

基本上,装饰器 @Type 为我们提供了一些辅助选项,如果我们想使用它们的话,例如我们..对象!因此,您可以有条件地 return 一种类型或另一种类型,因此验证是针对两种类型之一完成的:

class Feature {
  name: string

  @ValidateNested()
  @IsDefined()
  @Type(({ object }) => {
    if(object.option?.kind === 'color') return ColorFeature;
    else if(object.option?.kind === 'size') return SizeFeature;
    // Handle edge case where the previous ifs are not fullfiled
  })
  option: ColorFeature | SizeFeature
}

为了清洁起见,您甚至可以使用 switch case,以防您有更多类型:

  @ValidateNested()
  @IsDefined()
  @Type(({ object }) => {
    switch(object.option?.kind){
      case 'color':
        return ColorFeature;
      case 'size':
        return SizeFeature;
      case 'shape':
        return ShapeFeature;
      default:
        // Manage edge cases
    }
  })
  option: ColorFeature | SizeFeature | ShapeFeature

然后,您还必须在扩展 类 中使用验证装饰器,以便正确验证它们。