Creating Moment decorators for class-validator
Moment.js is on the way out, but if your project is using it and you’re missing a validator or two, you can still extend it.
As stated in the introduction, I know that Moment.js is now deprecated (and actually has been for quite some time), given its long-standing issues (bloat, lack of support for tree shaking, mutability, etc). My goal in this article is not to discuss whether it’s a good idea to use Moment.js in your project; I think that by now, the answer is pretty clear: it isn’t. But the truth is that we don’t always have a choice and we can’t just ditch it right now if there are other priorities.
In this article, I’ll explain how easy it is to create custom Moment.js validators/custom decorators for class-validator. To show this, I’ll share the code of the
MinDuration validators that I needed on my current project. As their name indicates, these validators respectively ensure that the value to check is a valid Moment duration object, or is a duration that is equal or above the configured minimum.
Generic validation function
First of all, let’s define a simple function to check whether a given value (string or null) is a valid duration object or not:
As you can see, this function is pretty simple. It receives a value assumed to be a duration and checks whether it really is one. For details about this logic, check out this SO question, as it works around some quirks.
The tests for this function are straightforward:
Now, let’s wrap our function into an actual Moment validator:
isDuration function is the validator function (which reuses our previous function) and the
IsDuration function is a TypeScript property decorator.
If you didn’t know, a TS decorator is actually.. a function. So this function receives the standard
ValidationOptions configuration object os Moment and returns the definition of the validator. When it calls the
ValidateBy function of moment, it defines how the validation needs to be performed and what message to return if validation fails.
Here are the tests for this validator:
Using this validator is as easy as adding
@IsDuration() to the property to validate.
The next validator extends the previous one to ensure that a duration value is equal or above a certain minimum.
Here’s the implementation:
This second validator is a bit more complex as it accepts an input value, which we’ve called
minDurationInMs (minimum duration in milliseconds). We pass that value as an argument to the decorator function, which passes it down to the
ValidateBy function as a constraint and is retrieved/passed to the
Once again, such validators are easy to test:
And as easy to use:
In this article, I’ve shown you how easy it is to create custom class-validator validation decorators using TypeScript and simple functions.
These are using the now officially dead Moment.js library, but you can create similar validators for any library or need you may have.
That’s it for today!