Safely Access Object Properties with `prop`

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

Social Share Links

Send Tweet

In this lesson, we’ll use a Maybe to safely operate on properties of an object that could be undefined. We’ll use our initial code as the basis for a prop utility function that can be reused with different objects and various property names. Instead of just blindly asking for a property, this version of prop will drop us into the safe confines of a Maybe, giving us a Just when the property exists and a Nothing for an undefined property. Once we’ve built up our own prop utility, we’ll refactor the code one more time to take advantage of the built-in prop utility provided by the crocks library.

Instructor: [00:00] Here, we have an object that represents a query string for paged records. We're getting the page property from the object, and passing that into our increment utility to get the next page.

[00:09] As we can see, the page property on the query string object has a value of two, and after calling inc on that value, we get back three. This works fine right up till that object gets sent to us without that page property, then we're going to get not a number.

[00:24] Let's use a Maybe type to avoid this unexpected result. I'm going to come up here to the top, and I'm going to pull in the Safe utility from Crocks. That will be require crocks/maybe/safe.

[00:38] As Safe is going to require a predicate function, I'm going to pull in a couple utilities from Ramda so that we can build up the predicate that we need. I'll pull in composeIsNil and Not. Those are all going to come in from the Ramda library.

[00:58] Then, I'm going to create a new function which I'm going to call isNotNil. I'm going to set that to equal compose, and I'm going to compose and say that we're going to call notAfterIsNil.

[01:10] Now, I have a predicate that I can use for Safe, I'll come down here and we'll call Safe with our isNotNil predicate. Passing in qs.page. We'll see down here we're going to get an object, let's take inc off of here and just make sure we're getting the object we expect. We're getting a Nothing.

[01:29] If I come up here and I put this page property back on the object, and I give it a value, you're going to see we'll get a Just of that value. Everything's working. In order to get the next page, we'll actually call this page.map. We'll map that over inc, we'll get a Just of four.

[01:48] We want to unwrap that, we'll use option. We'll give it a default value of one, and we'll get out just the four. If we go back to our object, we remove that property altogether. We'll get that default value of one.

[02:02] Now that we have this working, let's take it one step further and create a generic utility that we can use to grab a property off of any object in a Safe manner. I'm going to come down here, and I'm going to define prop. This is going to be our utility function.

[02:17] We're going to accept a property name, which we'll call prop name, then object. In our function, we're going to call Safe using our isNotNil predicate. Then we're going to reference that object, and we're going to grab it to prop name.

[02:33] This will pull the property off of the object, and if it's not nil, it will give us a Just wrapping the value that was in that property. If it is, we'll get back a Nothing. We can make sure this works by replacing our call to Safe down here with a call to our new prop utility. Passing in page as our property name and qs as our object.

[02:54] We'll see down here we still got our default of one. If I update the object up here, have a page property with a value, we're going to get that incremented value. This is a fairly common use of the Maybe type.

[03:08] Crocks actually comes with its own prop utility. Let's pull that in. I'm going to pull in cons prop, and that's going to equal call to require, passing in crocks/maybe/prop. Then we can comment out our implementation of prop, and we can also comment out our imports from Ramda and our isNotNil predicate.

[03:29] You'll see down here everything's still working as it was, because the Crocks implementation of prop is going to do the same thing for us. If I come down here and I get the page property off of this object, we'll see that we still get a Nothing, resulting in our default value.

[03:51] The added benefit to using the Crocks implementation, aside from the fact that you don't have to implement it yourself, is that it's curried. Which means I can come up here and I can call it with one argument, just the property name. And I get this reusable function that it's just waiting for an object.

[04:09] Now, you can come down here, and I can call SafePage, passing in query string. Everything will work as expected. If I wanted to use this on multiple objects that had a page property, I could just reuse the SafePage function wherever I needed.