Using Array.Reduce to Streamline Your JavaScript Object Validations
Nick Scialli (he/him)
Posted on April 27, 2020
Object validation in JavaScript can be tedious if you don't have a good framework in place. In this post, we'll use the Array.reduce
method to make object validation feel like a treat!
Manual Validations
Let's say we have a user
object and several criteria that need to pass to make it valid. Here are the properties and the criteria that they must meet:
prop | criteria |
---|---|
name | Longer than 2 characters |
password | Longer than 8 characters |
confirmPassword | Matches the password |
age | 18 or greater |
If we were to take a somewhat manual approach to validation, we might write something like this:
const user = {
name: "Bob",
password: "kaBob123",
confirmPassword: "kaBob123",
age: 19,
};
const errors = [];
if (user.name.length < 2) {
errors.push("User's name is too short");
}
if (user.password.length < 8) {
errors.push("User's password is too short");
}
if (user.password !== user.confirmPassword) {
errors.push("Password and confirmation do not match");
}
if (user.age < 18) {
errors.push("User must be at least 18 years old");
}
const isValid = errors.length === 0;
Our errors
array would get populated with any validation errors and, if the array had a length greater than 0, our isValid
variable would be false
.
Creating a Validation Framework
While this works alright for a small number of validations, I tend to prefer organizing larger sets of rules in an array, and using the reduce
method to determine if there are errors:
// Validation rules
const rules = [
{
test: (user) => user.name.length > 2,
message: "User's name is too short",
},
{
test: (user) => user.password.length >= 8,
message: "User's password is too short",
},
{
test: (user) => user.password === user.confirmPassword,
message: "Password and confirmation do not match",
},
{
test: (user) => user.age >= 18,
message: "User must be at least 18 years old",
},
];
// Test object against rules
const errors = rules.reduce((errs, rule) => {
const result = rule.test(user);
if (result === false) {
errs.push(rule.message);
}
return errs;
}, []);
const isValid = errors.length === 0;
Now, we have a consistent interface and can add rules just be adding additional objects to our array!
Creating a Reusable Validation Function
To extend the utility of our validator, we can create a function that takes an object, a set of rules, and returns errors and validation status. Let's create that function.
const validate = (obj, rules) => {
const errors = rules.reduce((errs, rule) => {
const result = rule.test(obj);
if (result === false) {
errs.push(rule.message);
}
return errs;
}, []);
return {
errors,
isValid: errors.length === 0
}
}
Now, we can use this function wherever we need to validate an object! Let's try with our previous example and use a user object that's not quite valid:
// Invalid user object
const user = {
name: "Bob",
password: "kaBob123",
confirmPassword: "kaBob12",
age: 17,
};
// Validation rules
const rules = [
{
test: (user) => user.name.length > 2,
message: "User's name is too short",
},
{
test: (user) => user.password.length >= 8,
message: "User's password is too short",
},
{
test: (user) => user.password === user.confirmPassword,
message: "Password and confirmation do not match",
},
{
test: (user) => user.age >= 18,
message: "User must be at least 18 years old",
},
];
// Validation function
const validate = (obj, rules) => {
const errors = rules.reduce((errs, rule) => {
const result = rule.test(obj);
if (result === false) {
errs.push(rule.message);
}
return errs;
}, []);
return {
errors,
isValid: errors.length === 0,
};
};
// Testing our object
const result = validate(user, rules);
// {
// errors:
// [ 'Password and confirmation do not match',
// 'User must be at least 18 years old' ],
// isValid: false
// }
I hope you enjoyed this exploration of using Array.reduce
to make our object validations just a bit more consistent and enjoyable.
Happy coding!
Posted on April 27, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 2, 2024
September 19, 2024
August 20, 2024