Skip to main content

Custom Rules

One of the main features of fluentvalidation-ts is that it is fully extensible, allowing you define your own custom validation logic and inject it via the .must rule.

The documentation page for the .must rule contains several examples that demonstrate the different ways in which you can define and consume custom rules, as well as a full API reference which outlines everything in detail.

The Gist

Custom validation logic is defined by way of a predicate function, which takes a value and returns a boolean (true/false) value indicating whether or not the value is valid.

You can pass custom validation logic directly into the .must rule with a predicate:

this.ruleFor('numberOfSocks').must((numberOfSocks) => numberOfSocks % 2 === 0);

If you want to reuse the logic, you could pull it out into a named function:

const beEven = (value: number) => value % 2 === 0;

Then you can just pass the named function into .must, like so:

this.ruleFor('numberOfSocks').must(beEven);

The predicate function can also depend on the value of the model as well as the value of the property:

this.ruleFor('numberOfSocks').must(
(numberOfSocks, model) => numberOfSocks === 2 * model.numberOfPants
);

You can define groups of rules by forming arrays:

const beEven = (value: number) => value % 2 === 0;
const bePositive = (value: number) => value > 0;

const beEvenAndPositive = [beEven, bePositive];

These arrays can be passed directly to the .must rule:

this.ruleFor('numberOfSocks').must(beEvenAndPositive);

You can also attach a custom message to your rule, alongside the predicate:

const beEven = {
predicate: (value: number) => value % 2 === 0,
message: 'Please enter an even number',
};

As before, you just pass this into the .must rule directly:

this.ruleFor('numberOfSocks').must(beEven);

Again, you can use arrays to compose rules together:

const beEven = {
predicate: (value: number) => value % 2 === 0,
message: 'Please enter an even number',
};

const bePositive = {
predicate: (value: number) => value > 0,
message: 'Please enter a positive number',
};

const beEvenAndPositive = [beEven, bePositive];

You can even compose groups of rules together by spreading or concatenating the arrays:

const newRuleGroup = [...ruleGroup, ...otherRuleGroup];