Object destructuring tips

Published 
JavaScript

Object destructuring is a very often used technique these days. It allows to destructure variables from an object, so we don't have to repeat our selves.

Attention

Destructured variables retain original reference!

An example of preserving object reference:

const orig = {
  foo: {
    bar: 1
  }
}

const { foo } = orig

console.log(foo.bar) // 1
console.log(orig.foo.bar) // 1

foo.bar++

console.log(foo.bar) // 2
console.log(orig.foo.bar) // 2

Simple object destructuring

const response = {
  name: 'Name',
  last_name:' Last Name'
}

Now we can access properties this way:

console.log(response.name, response.last_name)

But, this is much better, if you need to access these variables multiple times:

const { name, last_name } = response
console.log(name, last_name)

Rename variable names when destructuring

We can rename destructured variables.

const { name: newName, last_name: newLastName } = response
console.log(newName, newLastName)

Destructuring nested object properties

Conside we have this nested object:

const nestedObj = {
  levelOne: {
    levelTwo: {
      someProperty: 'hello'
    }
  }
}

No worries, we can destructure even a deep nested properties, it would be cumbersome, though 😄

const { levelOne: { levelTwo: { someProperty } } } = nestedObj
console.log(someProperty) // hello

But what if we try to access undefined properties?

const { levelOne: { testVar: { someProperty } } } = nestedObj

would throw Error: Cannot read properties of undefined (reading 'someProperty'), because testVar property doesn't exist inside levelOne property. We can avoid this by using default values:

const { levelOne: { testVar: { someProperty } = {} } } = nestedObj

Here, we assign an empty object to a testVar, thus it won't throw an error.


Reassign let variable with object destructuring

Sometimes we have a need to override let variable with a destructured variable.

Destructuring needs to be either after a let, const or var declaration or it needs to be in an expression context to distinguish it from a block statement

let emptyVar = null

const obj = {
  dunno: 'someValue'
}

;({ dunno: emptyVar } = obj)

Here we reassigning emptyVar with the value dunno from the obj by wrapping in parentheses (it's called expression).

Attention

Don't forget about semicolons, if you're not using them, put them right before expression, or you'll get unexpected errors.

The 3 Golden Rules

  1. Don't use nested destructuring on data that comes from any external data sources (such as REST APIs, GraphQL endpoints or files). You never know when these APIs change their response data, hence it is dangerous to do so.
  2. Don't use nested destructuring on function arguments that have long or complicated signatures. It makes it super hard to understand what the actually API of the function is, and you might get breaking behavior because someone decided to use your function, but in some edge case they do not provide you the valid input for you to destruct upon.
  3. Don't use destructuring to retrieve a value if you rely on order.