class-validator
class-validator copied to clipboard
feature: Conditional validation inside validation options
Description
Sometimes we need to validate a field based on another field in the dto.
Proposed solution
- it would be nice to have an option called
validateIf
which is a callback function with given object. example:
export class TestDto {
// ...
@IsNotEmpty()
@IsString()
type: string;
@IsUUID({ validateIf: o => o.type === "something" })
@IsEmpty({ validateIf: o => o.type === "something" })
@IsNotEmpty({ validateIf: o => o.type !== "something" })
albumId: string;
}
- the above example would do the job for me, but it would be nicer if we could group validation somehow like below:
export class TestDto {
// ...
@ValidationGroup([IsUUID(), IsEmpty()], { validateIf: o => o.type === "something" })
@IsNotEmpty({ validateIf: o => o.type !== "something" })
albumId: string;
}
or:
export class TestDto {
// ...
@ValidationGroup(o => {
if (o.type === "something" ) {
return [IsUUID(), IsEmpty()]
}
return [IsNotEmpty()]
})
albumId: string;
}
In general, it's really good to access current object when validating. for example I needed to set the max value of a number based on another field. I made my own decorator which works like:
@Max((o) =>
o.type === DiscountPlanType.Percentage ||
? 100
: false, // when false is passed, this will be skipped
)
One way to achieve what you want today is to use the existing validation groups combined with a function that, before validating, checks some property of the object to decide which groups to validate. Once you have figured that out, you can then call validate
with the groups passed in the ValidatorOptions
.
I'm not saying this to discard your suggestion, but this is a basis for comparison. What are the strengths and weaknesses of these approaches compared to one another? Personally I don't use groups, so I don't have a strong opinion about them.
I would suspect that with your approach it's easy for someone reading your code (either someone else or you in the future) to struggle to understand the intricacies of the logic since it would be scattered about in various decorators. Especially your last suggestion. The flexibility of this feature means that it's hard to make sure that you are programming with a consistent pattern. I am the type of person who would be reluctant to add features that, while powerful, could encourage bad practices and messy code.
That would be a very useful feature.
I'm currently actively migrating from Ruby On Rails to Express, and Rails implements this very conveniently - https://guides.rubyonrails.org/active_record_validations.html#using-a-symbol-with-if-and-unless.
The if condition can be specified for a specific validation, and not for the entire field. It is often necessary to have a different set of validations for a field depending on some parameters.
I believe this is a better description of #1455 and that we should go forward with this proposal.
I can't seem to find an open PR that fixes this issue with the proposed syntax for the validation function. #1455 and #2244 have different syntaxes, and #689 is specific to IsOptional
.
PR Welcome!
In my book, resolving this issue closes:
- #582
- #547
- #489
- #318
- #245
- #156
- #1455
- #1579 – this PR could be reworked to fix this issue @aoi-umi
- #2244 – this PR could be reworked to fix this issue @mario-orlicky
- #651
- #689
- #584
Can you please release this feature? I am waiting for this for so long..