ES6 Destructuring & Nested Optional Arguments

Image for post
Image for post

ECMAScript 6 (ES6) brings many new features. One of the features I’m most existed about is destructuring.

In a nutshell this allows you to extract values from an object by describing the object’s layout rather than accessing elements within it. This will become very important later as the examples get more complicated.

Disclaimer: ES6 is not fully supported by all browsers yet so most people will have to use a JavaScript compiler to convert the new ES6 syntax down to ES5 so that it will work on most browsers. I recommend Babel. Now that’s out of the way…

Let’s start off with some ES5 (the currently supported JavaScript):

function displayPerson(person) {
var description = person.name;
if (typeof person.dateOfBirth !== 'undefined') {
description += " was born on " + person.dateOfBirth;
}
console.log(description);
}

Seems simple enough. However, there’s a one big problem. The caller has to examine displayPersonto understand what properties are required and optional. It also doesn’t display any other properties that may be valid but just not used yet. We could use a comment block above to document the individual properties, but thats a hassle and may still require the caller to goto the file and look at the function.

Now let’s see how this could be handled in ES6:

function displayPerson({name: name, dateOfBirth: dateOfBirth}) {
let description = name;
if (typeof dateOfBirth !== 'undefined') {
description += " was born on " + dateOfBirth;
}
console.log(description);
}

All we’ve done is allow the nameand dateOfBirthto be assigned to a variable of the same name based on the structure of the incoming object. Since they are the same name we can make use of another ES6 feature. When object property names are the same name as the variable they can be collapsed:

function displayPerson({name, dateOfBirth}) {

This looks neater. But we can also use default valuesto indicate that the dateOfBirthis optional:

function displayPerson({name, dateOfBirth = undefined}) {

This may seem redundant since dateOfBirth will be undefined if not provided anyway. But you could use a different default value or expression. I like to use the default value to explicitly state that it is optional.

A More Complex Example

Let’s extend this to something more complicated and practical like processing a nested object:

function displayPerson({name, address: {street, postcode}}) {
console.log(name + " lives at " + street);
}

It would be safe to assume as the caller that all of the variables are required. If addressis optional we get into real trouble now:

displayPerson({name: 'John'})
// undefined is not an object

We can make address optional by assigning an empty object:

function displayPerson({name, address: {street, postcode} = {}}) {
console.log(name + " lives at " + street);
}

It prevents an attribute from being undefinedin the when extracted from the object. We would probably still need custom error handling code when things are missing.

Enforcing Required Values

Some people would call this a hack, but not at all. The default values (or expressions in this case) are only evaluated if the property doesn’t exist. We can use this logic in our favour:

function required(field) {
throw new Error(field + ' is required!');
}

Self-documenting APIs

Heres an example response of the three most recent tradesfrom independentreserve.com:

{
"Trades":[
{
"TradeTimestampUtc":"2016-01-10T03:26:00.1995957Z",
"PrimaryCurrencyAmount":0.30051550,
"SecondaryCurrencyTradePrice":449.02
}, {
"TradeTimestampUtc":"2016-01-10T03:22:20.9286286Z",
"PrimaryCurrencyAmount":0.30138850,
"SecondaryCurrencyTradePrice":450.16
}, {
"TradeTimestampUtc":"2016-01-10T03:09:35.2613933Z",
"PrimaryCurrencyAmount":0.30137260,
"SecondaryCurrencyTradePrice":448.91
}
],
"PrimaryCurrencyCode":"Xbt",
"SecondaryCurrencyCode":"Usd",
"CreatedTimestampUtc":"2016-01-10T03:29:23.4256336Z"
}

It’s very possible that if we write some code to process these we will not need all the data available. However, without pasting an example response in a comment above the code we would have no idea what fields are available to us or what format they are in without making the call again.

This is especially annoying for unit testing where we should be mocking these out and only need to see what the response format is without needing to make a request.

function example(value) {
return undefined;
}

Originally published at http://elliot.land on January 10, 2016.

Written by

I’m a data nerd and TDD enthusiast originally from Sydney. Currently working for Uber in New York. My thoughts here are my own. 🤓 elliotchance@gmail.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store