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?
const arr = undefined
arr[2] // TypeError is thrown
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
?
const arr = null
arr.length // TypeError is thrown
One solution is to do the “value or default” approach to keep the errors at bay:
const arr = undefined
const xs = arr || []
xs[2] // undefined
xs.length // 0
An approach we could take to avoid the errors being thrown would be to use ramda’s prop
helper:
import prop from 'ramda/src/prop'
const arr = undefined
prop(2, arr) // undefined
prop('length', arr) // undefined
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
:
import propOr from 'ramda/src/propOr'
const arr = undefined
propOr({}, 2, arr) // {}
propOr(0, 'length', arr) // 0
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.
import path from 'ramda/src/path'
const data = {
courses: {
abc123: {
title: 'How To Build a Tiny House',
dueAt: '2018-01-30'
}
}
}
// getCourseTitle :: String -> String | undefined
const getCourseTitle = courseId =>
path(['courses', courseId, 'title'])
getCourseTitle('abc123')(data) // "How To Build a Tiny House"
getCourseTitle('def456')(data) // undefined
Try this code in the ramda REPL
Or if we’d always like to default to a value, we can use pathOr
:
import pathOr from 'ramda/src/path'
const data = {
courses: {
abc123: {
title: 'How To Build a Tiny House',
dueAt: '2018-01-30'
}
}
}
// getCourseTitle :: String -> String
const getCourseTitle = courseId =>
pathOr('My Course', ['courses', courseId, 'title'])
getCourseTitle('abc123')(data) // "How To Build a Tiny House"
getCourseTitle('def456')(data) // "My Course"
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,
Robert