Creating Moment decorators for class-validator

Sébastien Dubois / October 25, 2020

3 min read

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.

Time. Picture courtesy of https://unsplash.com/@neonbrand

Class-validator is a pretty popular JS/TS validation library based on decorators. It provides many built-in validators, but can also be extended quite easily.

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 IsDuration and 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:

IsDuration validator

Now, let’s wrap our function into an actual Moment validator:

The 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.

MinDuration validator

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 minDurationfunction using args?.constraints[0].

Once again, such validators are easy to test:

And as easy to use:

Conclusion

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!

PS: check out my Dev Concepts books, join the Software Crafters community, the Personal Knowledge Management community, and come say hi on Twitter!
Discuss on TwitterEdit on GitHub