Safely Access Nested Object Properties with `propPath`

Andy Van Slaars
InstructorAndy Van Slaars
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 5 years ago

In this lesson, we’ll look at the propPath utility function. We’ll ask for a property multiple levels deep in an object and get back a Maybe. We’ll get a Just when the property exists at our path and a Nothing if any part of the path is undefined.

Instructor: [00:00] I have an example user object. I'm using standard dot notation to get the user's postal code from a nested address object. We're getting a value, but it's possible that this property could be missing from our object.

[00:11] If I were to come up here and change this by renaming it, we'll see down here that we get undefined. What we want to do in the case where we don't get the postal code is return some kind of a default value. I can do this with just an or, and I can say, "Not available." We'll see that in the case where postal code doesn't exist, we're going to get that "Not available" string.

[00:36] Otherwise, we'll get our postal code. The real problems start if our address isn't available. If I come up here and I rename this so it's not a valid piece of that path, we'll see that we're going to get a type error that it cannot read the property postal code of undefined.

[00:53] The problem here is that we have an undefined in the middle of our path, which is actually going to throw an exception rather than just give us an undefined. This is a little harder to recover from. We're going to reach for a maybe. What we'll do is we'll import the utility from the Crocks library just called "propPath."

[01:10] We'll get that with require('crocks/maybe/proppath'). Then, we'll update this, and we'll get rid of our or here. We'll save this. Then what we'll do is we're going to call propPath, and we're going to pass in the path we want within the property as an array of strings and then the object that we want.

[01:42] The object that we're going to take this from is going to be user. Then, our path is going to be address followed by postal code. We'll see that we get a just with our postal code. If I come up here and I get rid of that, and we're going to get a nothing. If I come up here and I get rid of address, we're also going to get a nothing.

[02:07] We've avoided our type error. Now all we have to do to use our default value in either one of those cases is come down here and call option to unwrap our value. We'll give it a default for the case where we have a nothing. We'll say that we're getting our zip code. Then if I take address out of the equation, we get not available. If address is there but it doesn't have postal code, we get not available again.

[02:37] Just like the other utilities in Crocks, this is curried. We can take the first portion of this, and we can break it out into its own reusable function. Define get postal code. We'll set that to equal call to propPath with just the array of properties for our path. Then we can come down here, and we can call our get postal code function passing in user.

[03:08] Then, calling option on that. Everything will continue to work as expected, but now we have this reusable function that we can apply to multiple objects...

Paweł Waszczyński
Paweł Waszczyński
~ 5 years ago

Is it possible to make it look like:

getPostalCode(user) // returns real postal code OR not available

and put option as a part of postal code? I looked for call function in crocks but I didn't found it. Otherwise I would look something similar to:

// call option function with argument `not available` on result of propPath(['address', 'postalCode']
const getPostalCode = compose(call('not available', 'option'), propPath(['address', 'postalCode'])
const zip = getPostalCode(user)
Markdown supported.
Become a member to join the discussionEnroll Today