It’s a better way of handling
undefined. Instead of writing an if statement, ternary expression, or
&& shorthand to check if a value is present you can just
map over it instead and assign the result of this expression or return it. You can also chain operations together, often leading to much cleaner code.
See the project Readme to get started quickly.
Why did I create it?
onClick() handlers and fancy menus with hover states.
Also, like React Native itself, I have embraced flow which I’d strongly recommend, although I have a bias towards statically typed languages.
What became obvious after a few months into a sizeable project is that dealing with
null values and having just come from using some of them, I was feeling the pain of not being able to write simpler code to handle these cases.
I often think that programmers are particularly good at dealing with pain. They overcome hurdles on a daily basis and bang their heads against a wall until it just works. Over time they will forget why they are doing something a certain way, other than the fact that it didn’t work any other way.
“The most dangerous phrase in the language is,
‘We’ve always done it this way.’” — Grace Hopper
The main problem with dealing with
null values like you would in Kernigan & Ritchie’s C is that your control flow is very constrained to writing statements instead of expressions. Every time you have a possibly
undefined value you need to write an
if statement to accompany it. Sometimes you can get away with using the
&& shorthand or a ternary expression. This might just be fine if you have to check only one value, but what about two, three, or five even plus some extra logic in there too. Eventually things get out of hand and you end up with some nested nightmare that others have coined the ‘pyramid of doom’.
The Promise abstraction was the answer to this, quickly followed by the async function variant.
‘Wait!’ I hear you say. I can just use some handy utility function to reach inside of my data (and also provide a default). Well you could, and that would be your choice, but what you’re forgetting is that these functions usually take a
Array<string>. This is fine if you want to live by the seat of your pants. But if you’ve already committed to making your application typed using flow then this won’t give you any safety guarantees, or provide an easy path for maintenance either. You’ll have a stringly typed mess rather than strongly typed code.
map() and you’re most of the way there.
if let syntax, I can also (optionally) transform it using the
By promoting primitive
undefined values to object types that have member functions — by wrapping them in a containing object — we can achieve something that resembles this paradigm.
Maybe because they’ve already been using them with
Ways to use it
I’d recommend checking out the project Readme for some simple examples.
In practical terms there’s no limit to its usage. I’ve seen it adopted by my team in these areas so far:
- HOCs (Higher-Order Components)
- Redux (actions, reducers, selectors & middleware)
- Api client
- Other utility and transformation functions
It becomes easier to use something like this once it’s supported at the library level and by the ecosystem. For example, you can’t return a
Maybe type in
render() of React’s
Component just yet.