Ramda Chops: Safely Accessing Properties


Thanks to @joshsloat and @zerkms for their review of this post.

One of the most prevalent causes of bugs I’ve seen in latter-day JavaScript revolves around expectations with regard to data modeling. With the rise of react, redux, et al, many of us store our application state in an object whose keys and hierarchy can easily change, leaving us sometimes with or without values that were in fact expected: for example, undefined is not a function or trying to call .map(...) on a non-mappable data type (such as null or undefined). While there are any number of solutions for this issue that might even include diving into algebraic data types, the ramda library gives us a few helper methods that we can use right away to dig into our data structures and extract values:

Other ramda posts:

prop & propOr

What happens normally if you expect an array, try to access the third item (index position 2), but are actually provided undefined instead of an array?

What happens if you try to access the length property on what you think should be an array but ends up being null or undefined?

One solution is to do the “value or default” approach to keep the errors at bay:

An approach we could take to avoid the errors being thrown would be to use ramda’s prop helper:

Ramda’s length function would accomplish a similar goal for prop('length').

But if we want a default to be returned in lieu of our data not being present, we can turn to propOr:

If you need to select multiple properties without fear, then the props or pick functions may be for you.

path & pathOr

What if we are working in a deeply nested data structure where multiple keys in our hierarchy may or may not exist? Enter path and pathOr. These work similarly to prop and propOr except that they use an array syntax to dive into data structures and ultimately check for a value, whereas the prop family checks for a property’s presence.

Try this code in the ramda REPL

Or if we’d always like to default to a value, we can use pathOr:

Try this code in the ramda REPL

As I said before, there are many different ways to solve this problem, but I’ve found the propOr and pathOr family of ramda functions to be a great starting point.

Until next time,