How to avoid null and undefined by using Maybe and Result (Either) in javascript
There are many tools, functions, and techniques to evaluate if a variable exists if it is well defined and not null. While working on a project following the functional programming paradigm, I practiced one that deserves special attention.
These two methods come from an external library that offers several functions for functional programming in javascript : Folktale.
To show the principle, let’s describe two examples.
Case 1: Optional field
I want to test in my backend the content of a non-mandatory form field from the frontend.
The first question is: did the user enter any information?
If the answer is “maybe,” then we use Maybe()
.
Maybe() can have 2 states:
Nothing()
: no valueJust()
: a value
The method consists in initializing the value of the form field with Maybe.Nothing()
and when the user enters a value, to replace it with a Maybe.Just("theEnteredValue")
.
So when the form is submitted, we can retrieve the value in the object of this Maybe with the matchWith()
function and apply the desired process.
In the code:
// myVariable comes from the formmyVariable.matchWith(Nothing : () => queFaireSiAucuneValeur(),Just : dataObject => traitementAAppliquer(dataObject.value)});
Other functions allow to test the variable myVariable to know its state, like for example :
// myVariable contains Maybe.Nothing()myVariable.isJust //falsemyVariable.isNothing //true
Case 2: The result of a query to the DB
I want to evaluate a DB query result and have either a value or an error.
In this case, we use Result()
.
Result() can have 2 states:
Error()
: to contain errorsOk()
: to contain the result
The method consists of returning the request’s result with an Ok()
and returning an Error()
in the error handling.
So when receiving the response, we don’t bother to test the result. We simply decompose the Result()
with the matchwith()
function:
myVariable.matchwith(Error: err => fonctionDeGestionErreur(err.value),Ok: result => traitementAAppliquer(result.value)});
Practical examples
To implement these examples, you need to create a node.js project using NPM :
- Create a directory
- In this directory run the command
npm init
. - Follow the wizard
- Install Folktale:
npm install --save folktale
- Open index.js in an editor
Maybe()
example
const Maybe = require(‘folktale/Maybe’);// const variable = Maybe.Nothing();const variable = Maybe.Just(‘great value’);variable.matchWith(Nothing: () => console.log(‘Sorry, no value here’),Just: dataObject => console.log(‘Value is : ‘ + dataObject.value),});
Result()
example
const Result = require(‘folktale/Result’);// const variable = Result.Error(‘this is an error !’);const variable = Result.Ok(‘Expected result’);variable.matchWith(Error: err => console.log(err.value),Ok: dataObject => console.log(‘Value is : ‘ + dataObject.value),});
If we alternate between the two possible values of the variable by moving the comments, the result changes during the execution with node index.js
.
Conclusion
I did not have to deal with undefined
or null
values with these methods. It requires some preliminary work when defining the values or the data retrieval functions, but in the end, it's very comfortable to use!
It can lead to a few acrobatics if you add Redux for React projects, but in the end, it is speedy to set up, and it allows you to anticipate the different situations upfront.
Variable typing works very well with Flow, but I regret that this library is not compatible with TypeScript (when I write these lines). There are other libraries in this case if you want to implement them.
It is a technique I still use, even outside of functional programming projects!
And you, are you familiar with these techniques ? Do you have other methods ? Don’t hesitate to share them in the comments.
Happy coding !!