Simple validation
A few basic input validation functions in plain JavaScript
The way of kata
Kata is an exercise for muscle memory. It's not intended to fill your brain with information but train your fingers to react. The information is there to give you the why, but your fingers need to learn the how.
The material on this page is presented in a specific order — from least specific to highly technical. You will learn the most by jumping in as soon as you have some idea of what you should do. Once you're done, read the rest of the material and check your solution.
All katas are designed to be doable without using 3rd party libraries (and, in fact, the point is to also learn how to do what these libraries do).
To make the best of katas, observe the following rules.
- Don't rush.
- When stuck, take a break and do something unrelated.
- Do not copy/paste code. Always retype everything.
- Do not use AI tools to generate code.
- Try to do something that wasn't in the instructions, experiment.
- Repeat the kata from time to time, even if you think you've got it.
- You have mastered the kata once you are able to complete it without thinking too much.
Remember, the goal is not to get it done, but to get some practice.
Introduction
In this exercise, you will write a series of functions for validating user input. Input validation is a critical element of any program that deals with user input. It serves the purpose of both guiding the user towards successful completion of forms, and it also defends the application against intentionally malformed input that is designed to compromise your program. Keep this in mind while doing this exercise.
Skills you will acquire
- User input validation
Objective
Write functions to validate the following:
- Field is required and value is specified
- Field contains a valid email address
- Field contains a valid date in
YYYY-MM-DDformat. - Field contains at least N characters
- Field contains at most N characters
- Field contains a numeric value (either an integer or a decimal number)
- Field contains a value that satisfies any combination of other validators
The validator should return a string that says what went wrong. If there is no error, it should return an empty string.
Check your solution
- Catch fields that are blank
- Catch fields that only comprise of whitespace as blank
- Catch fields that are filled in but aren't a valid email address
- Catch invalid month and date numbers in dates such as
2024-44-99 - Catch fields that are filled in but have more characters than specified
- Catch fields that are filled in but have less characters than specified
- Ignore trailing and leading whitespace when counting characters for length limits
- Correctly count emoji or characters written in some non-English languages
(e.g.,
🦆as 1) - Catch invalid numeric values such as
1.2.3or.32 - When combining multiple validators, the the first failing validation is reported
- When combining multiple validators
Tools
Keep in mind
All inputs are strings.
A validator could be written as a function that takes the input as its only argument and returns an empty string when there is no error, or an error message specific to what it validates.
When you are deciding what the error message should say, consider two possible patterns:
- The string could represent a message intended for the end user
- The string could represent an identifier that can be later mapped to a message for the end user
The second pattern is slightly more complex, but it gives the interface code more flexibility in how it will report the error (e.g., the same constraint may have different meanings depending on the context).
Validators cannot validate anything that is validated by another validator. For example, an email validator cannot also validate that field is missing a value.
Some validators have parameters (e.g., "contains at least N characters" has "N" as a parameter), and some do not.
A function that combines multiple validators can be seen as a validator that has other validators as parameters.
A standards-compliant email address may include ludicrous things that are not normally seen as an email address in practical everyday use. Research various ways to validate email addresses and pick a pragmatic approach.
When testing that something is in a valid format, do not forget that just because it can be used as an input in some cases, it doesn't mean it's valid. For example:
parseFloat('2a') // => 2
In the example, '2a' is not a valid number, but parseFloat() will let you
treat it as a valid input. Your validator should fail this kind of input.
In many cases, using regular expressions is the right approach to test input
validity.
Try also playing with other ideas such as making each validator a class.
Reading list
Hints & spoilers
Hint: Implementing parametrized validators
function validateMaxLength(length) {
return function (value) {
// This is the actual validator function
}
}
The example shows what is commonly known as 'currying'. The outer function's
sole purpose is to capture and "hold onto" the length parameter for the
inner one. The inner function is returned by the other function but keeps
access to the length variable (parameters are variables) even after it is
returned (this phenomenon is called 'closure').