This release includes a few bug fixes and small improvements, but also brings in some very useful extensions for the .must
rule which make it a lot easier to define custom validation rules and associate custom error messages with them.
Summary
- Updated dev dependencies
- Bug fixes and improvements for the
.scalePrecision
rule - Enhanced capability of the
.must
rule to make it easier to configure reusable custom rules
Updated dev dependencies
All development dependencies have been updated to the latest version.
Bug fixes and improvements for .scalePrecision
- Fixed an issue whereby the validation logic was incorrect for negative numbers
- Improved the implementation under the hood to be more stable
- Added a warning to the documentation regarding floating point arithmetic
New features for .must
This is the big change in this release, which makes it a lot more convenient to define custom validation logic that can be reused across several validators.
Previously it was possible to create reusable validation logic by defining named predicate functions:
// v2.0.0 and below
// Define some custom validation logic:
export const beNumeric = (value: string) => !isNaN(Number(value));
// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
.must(beNumeric);
This is great, but in order to specify a custom error message we are forced to make a call to .withMessage
as well:
// v2.0.0 and below
// Define some custom validation logic:
export const beNumeric = (value: string) => !isNaN(Number(value));
export const beNumericErrorMessage = 'Please enter a number';
// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
.must(beNumeric)
.withMessage(beNumericErrorMessage);
This works, but it feels clunky. Ideally we'd have a way of wrapping up both the validation logic and the error message into a single named variable.
Well, v2.1.0 brings exactly that:
// v2.1.0 and above
// Define some custom validation logic:
export const beNumeric = {
predicate: (value: string) => !isNaN(Number(value)),
message: 'Please enter a number',
};
// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
.must(beNumeric);
Not only that, but you can also compose multiple custom rules together into arrays of rules which .must
will accept:
// v2.1.0 and above
// Define some custom validation logic:
export const beNumeric = {
predicate: (value: string) => !isNaN(Number(value)),
message: 'Please enter a number',
};
export const beAnInteger = {
predicate: (value: string) => Number(value) % 1 ===0,
message: 'Please enter a whole number',
};
export const bePositive = {
predicate: (value: string) => Number(value) > 0,
message: 'Please enter a positive number',
};
export const bePositiveInteger = [beNumeric, beAnInteger, bePositive];
// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
.must(bePositiveInteger);
As you can see, these additions to the API of the .must
rule open up a ton of new possibilities when it comes to defining custom validation rules. The examples here have only touched on these possibilities - see the README for more details.