Website-Suche

typescript - class-validator diskriminierte Union-Typen validieren


Ich habe ein Mongoose-Discriminator-Schema, was bedeutet, dass die Daten je nach einem der Attribute unterschiedlich sein werden.

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

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

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

Was ist der korrekte Weg, die Feature-Klasse zu validieren, sodass sie nur 2 verschiedene Arten akzeptiert?

Antwort #1

Es kann erreicht werden, indem validateNested() zusammen mit dem class-transformer-Discriminator verwendet wird.

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

Antwort #2

Ich habe viel Zeit damit verbracht, und ich habe schließlich einen saubereren Weg gefunden, es zu tun als die derzeitige Antwort.

Grundsätzlich gibt uns der Dekorator @Type einige Hilfsoptionen, wenn wir sie verwenden möchten, zum Beispiel das Objekt! So können Sie bedingt einen Typ oder den anderen zurückgeben, sodass die Validierung über einen der beiden Typen erfolgt:

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 kannst sogar einen switch case oder ein Record der Sauberkeit halber verwenden, falls du mehr Typen hast:

  @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

Dann müssen Sie in den erweiterten Klassen auch Validierungsdekorationen verwenden, damit sie korrekt validiert werden.

Verwandte Artikel