PhoenixDAO is a project that has been started by Hydro community members to bring true decentralization through a fork of the protocols. This includes adding a community based DAO which will oversee…
One aspect of JavaScript development that many developers struggle with is dealing with optional values. What are the best strategies to minimize errors caused by values that could be null
, undefined
, or otherwise uninitialized at runtime?
Some languages have built-in affordances for those circumstances. In some statically typed languages, you can say that null
and undefined
are illegal values, and let your programming language throw a TypeError at compile time, but even in those languages, that can't prevent null inputs from flowing into the program at runtime.
To get a better handle on this problem, we need to understand where these values can come from. Here are some of the most common sources:
I always pass inputs I receive from the network, database, or user input through a hydrating function. For example, I’ll use redux action creators that can handle undefined
values to hydrate user records:
Sometimes, you’ll need to display different things depending on the current state of the data. If it’s possible to display a page before all of the data is initialized, you may find yourself in that situation. For example, when you’re displaying money balances to a user, you could accidentally display a $0 balance before the data loads. I’ve seen this upset users a number of times. You can create custom data types which generate different outputs based on the current state:
The code above is a state machine which makes it impossible to display invalid states. When you first create the balance, it will be set to an uninitialized
state. If you try to display a balance while the state is uninitialized
, you’ll always get a placeholder value ("--
") instead.
To change that, you have to explicitly set a value by calling the .set
method, or the setBalance
shortcut we defined below the createBalance
factory.
The state itself is encapsulated to protect it from outside interference to make sure that other functions can’t grab it and set it to an invalid state.
In your own functions, you can avoid creating null
or undefined
values to begin with. There are a couple ways to do that built into JavaScript that spring to mind. See below.
I never explicitly create null
values in JavaScript, because I never really saw the point of having two different primitive values that essentially mean "this value does not exist."
Since 2015, JavaScript has supported default values that get filled in when you don’t supply a value for the argument or property in question. Those defaults don’t work for null
values. That is usually a bug, in my experience. To avoid that trap, don’t use null
in JavaScript.
If you want special cases for uninitialized or empty values, state machines are a better bet. See above.
There are a couple of features that can help you deal with null
or undefined
values. Both are stage 3 proposals at the time of this writing, but if you're reading from the future, you may be able to use them.
As of this writing, optional chaining is a stage 3 proposal. It works like this:
Also a stage 3 proposal to be added to the specification, “nullish coalescing operator” is basically a fancy way of saying “fallback value operator”. If the value on the left is undefined
or null
, it evaluates to the value on the right. It works like this:
If the future hasn’t arrived, yet, you’ll need to install @babel/plugin-proposal-optional-chaining
and @babel/plugin-proposal-nullish-coalescing-operator
.
If a function may not return with a value, it might be a good idea to wrap it in an Either. In functional programming, the Either monad is a special abstract data type that allows you to attach two different code paths: a success path, or a fail path. JavaScript has a built-in asynchronous Either monad-ish data type called Promise. You can use it to do declarative error branching for undefined values:
You could write a synchronous version of that if you want, but I haven’t needed it much. I’ll leave that as an exercise for you. If you have a good grounding in functors and monads, the process will be easier. If that sounds intimidating, don’t worry about it. Just use promises. They’re built-in and they work fine most of the time.
Arrays implement a map
method which takes a function that is applied to each element of the array. If the array is empty, the function will never be called. In other words, Arrays in JavaScript can fill the role of Maybes from languages like Haskell.
A Maybe is a special abstract data type that encapsulates an optional value. The data type takes two forms:
Here’s the gist of the idea:
This is just an example to demonstrate the concept. You could build a whole library of useful functions around maybes, implementing other operations like flatMap
and flat
(e.g., to avoid Just(Just(value))
when you compose multiple Maybe-returning functions). But JavaScript already has a data type that implements a lot of those features out-of-the-box, so I usually reach for that instead: The Array.
If you want to create a function which may or may not produce a result (particularly if there can be more than one result), you may have a great use-case to return an array.
I find the fact that map
won't be called on an empty list very useful for avoiding null
and undefined
values, but remember, if the array contains null
and undefined
values, it will call the function with those values, so if the function you're running could produce null
or undefined
, you'll need to filter those out of your returned array, as demonstrated above. That could have the effect of changing the length of the collection.
In Haskell, there’s a function maybe
that (like map
) applies a function to a value. But the value is optional and encapsulated in a Maybe
. We can use JavaScript's Array
data type to do essentially the same thing:
maybe
takes a fallback value, then a function to map over the maybe array, then a maybe array (an array containing one value, or nothing), and returns either the result of applying the function to the array's contents, or the fallback value if the array is empty.
For convenience, I’ve also defined a toMaybeArray
function, and curried the maybe
function to make it most obvious for this demonstration.
He enjoys a remote lifestyle with the most beautiful woman in the world.
If you have ever visited any major Ecommerce website, there is a 100% chance you have seen your viewed products again stacked in a panel. It’s almost as if the website is keeping track of your interests, well you are not crazy...
Want to hire mobile app developer USA? Hmm! The most tedious task is to hire dedicated mobile app developers that fit perfectly in your shoes. We are living in an era where most of the business…
I remember our first house, we built and I was so very proud of that fact. The first time we visited the construction site, I thought to myself “those guys must be nervous seeing us come down. The…