typescript - class-validator validera diskriminerad unionstyp


Jag har ett Mongoose-discriminator-schema, vilket betyder att datan kommer att vara olika beroende på en av attributen.

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

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

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

Vad är det rätta sättet att validera Feature-klassen så att den bara accepterar 2 olika typer?

Svar #1

det kan uppnås genom att använda validateNested() tillsammans med 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;
}

Svar #2

Jag tillbringade mycket tid med detta, och jag hittade äntligen ett renare sätt att göra det än det nuvarande svaret.

I grund och botten ger dekoratören @Type oss några hjälpalternativ om vi vill använda dem, såsom.. objektet! Så, du kan returnera den ena typen eller den andra beroende på villkor, så valideringen görs över en av de två typerna:

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
}

Du kan till och med använda en switch case eller någon Record för tydlighetens skull om du har fler typer:

  @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

Då måste du också använda valideringsdekorationer i de utökade klasserna, så att de valideras korrekt.

Relaterade artiklar