'class-validator validate union type
I have a mongoose discriminator schema, which mean the data will be different according to one of the attributes.
class Feature {
name: string
option: ColorFeature|SizeFeature
}
class ColorFeature {
kind: 'color'
color: string
}
class SizeFeature {
kind: 'size'
size: number
}
What is the correct way to validate the Feature
class so that it only accepts 2 different kinds?
Solution 1:[1]
it can be achieved by using validateNested()
together with 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;
}
Solution 2:[2]
I spent a lot of time with this, and I finally found a cleaner way of doing it than the current answer.
Basically, the decorator @Type
gives us some helper options if we want to use them, such us.. the object! So, you can return one type or the other conditionally, so the validation is done over one of the two types:
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
}
You can even use a switch case
for cleanliness sake in case you have more types:
@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
Then, you also have to use validation decorators in the extended classes, so that they are correctly validated.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Eduardo Poiate |
Solution 2 |