# get or prop

The safe way to access Objects is to create a get function. For objects you know the shape of, meaning you know what properties and value types they typically have, you can create these yourself.

const getFirstName = person => {
    if(person) {
        return person.firstName
    }
    return undefined
}

Then you can test it to verify it's safe:

expect(getFirstName(person)).to.equal('Jesse')
expect(getFirstName(undefined)).to.equal(undefined)

This is such a common thing to do that Lodash has a get function, Ramda and Sanctuary have prop.

import { get } from 'lodash'

console.log(get(person, 'firstName')) // Jesse
console.log(get(person, 'fistName')) // undefined
console.log(get(undefined, 'firstName')) // undefined

# Dem Deep Gets

Deeply nested properties, however, require null or null operators:

const getStreetAddress = person => {
    if(person && person.address && person.address.home) {
        return person.address.home.street
    }
    return undefined
}

Using the operator could be re-written as:

const getStreetAddress = person =>
    person.address?.home?.street

It's less code and safer just to use get with the path:

const getStreetAddress = person =>
    get(person, 'person.address.home.street')

Now those are just Objects. Arrays require you to do runtime type checking:

const getFirstHomePhone = person => {
    if(
        person 
        && person.address 
        && person.address.home 
        && Array.isArray(person.address.home.phone)
        ) {
        return person.address.home.phone[0]
    }
    return undefined
}

... or you could just use get:

const getFirstHomePhone = person =>
    get(person, 'person.address.home.phone[0]')

This also works great for deeply nested JSON data structures you often get back from REST API's as well as SOAP and XML you've parsed to JSON.

# Default Values

You'll often configure your Node API using the config library. One thing you'll run into when configuring for different development environments like dev, qa, and prod is default values in case the configuration intentionally doesn't exist. In the browser, if you run into configuration errors, you just fall back to the defaults so the application still works.

You can do that using get or Ramda's propOr:

const url = get(configuration, 'services.emailURL', 'http://dev.server.com/email')

If it can't find the services.emailURL path on configuration, or if configuration is undefined, it'll just default to that dev url, 'http://dev.server.com/email'.

# Conclusions

Using get ensures you never have errors. The Object can change it's property names on you, or even be undefined, but your program still won't have errors. It also helps you avoid error prone, verbose null checks and results in smaller code. As we'll see in future chapters, using this get function will allow us to compose her very flexibly into a variety of ways.