feature: Range decorator for numbers
Description
There are two string length check decorators: @MinLength and @MaxLength.
Additionally, there is a string decorator @Length(min, max) which checks if string length is in range between min and max.
As a developer, having @Min and @Max decorators for numbers, which works similar to @MinLength and @MaxLength, I would expect the third, @Range(min, max) decorator, to be delivered with class-validator.
Proposed solution
Create a new @Range decorator for numbers, which is a combination of Min and Max decorators.
Code implementation suggestion:
import { ValidationOptions } from '../ValidationOptions';
import { buildMessage, ValidateBy } from '../common/ValidateBy';
export const RANGE = 'range';
/**
* Checks if the first number is greater than or equal to the second and less than or equal to the third.
*/
export function range(num: unknown, min: number, max: number): boolean {
return typeof num === 'number' && typeof max === 'number' && typeof min === 'number' && min <= num <= max;
}
/**
* Checks if the value is greater than or equal to the allowed minimum value and less than or equal to the allowed maximum value.
*/
export function Range(minValue: number, maxValue: number, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: RANGE,
constraints: [minValue, maxValue],
validator: {
validate: (value, args): boolean => range(value, args?.constraints[0], args?.constraints[1]),
defaultMessage: buildMessage(
eachPrefix => eachPrefix + '$property must be greater than or equal to $constraint1 and less than or equal to $constraint2',
validationOptions
),
},
},
validationOptions
);
}
It would simplify code for typical use case like this:
@Min(1)
@Max(10)
priority: number
The same conditions with new decorator would look like this:
@Range(1, 10)
priority: number
Take into account that there may be conflicts with using Range as a decorator name, as shown in the screenshots. This name is already associated with the Range interface in the DOM API, which could lead to confusion or potential conflicts.
Possible alternatives:
@ValueRange()
@MinMaxRange()
@Between()
@WithinRange()
More on Range:
interface Range
A fragment of a document that can contain nodes and parts of text nodes.
https://developer.mozilla.org/en-US/docs/Web/API/Range
Have nothing against name changing suggestion from @bzhn 👍. Will add another suggestion: @NumRange