Wanna see something cool? Check out Angular Spotify 🎧
All Articles

Uncaught TypeError: Cannot read property 'name' of undefined

It is a very common error when working with object and array to get a TypeError: Cannot read property 'name' of undefined. This happens when we try to access a property of a value that is undefined or null in JavaScript.

uncaught type error

var movie = {
  name: 'Interstellar',
  director: {
    name: 'Christopher Nolan',
    born: 'July 30, 1970',
  },
  music: 'Hans Zimmer',
}
console.log(movie.director.name) //Christopher Nolan
console.log(movie.music.name) //undefined
console.log(movie.cast[0].name) //Uncaught TypeError: Cannot read property '0' of undefined

var obj = {}
console.log(obj.prop1.deepProp) //Uncaught TypeError: Cannot read property 'deepProp' of undefined

Workarounds

There are some ways to avoid this kind of errors.

1. The simplest approach is using the logical AND operator &&.

var obj = {}
console.log(obj.prop1.deepProp) //Uncaught TypeError: Cannot read property 'deepProp' of undefined
console.log(obj.prop1 && obj.prop1.deepProp) //undefined

This works because the && operators actually return one of the value of the specified operands if these operators are used with non-Boolean values. The rule is described as. If we had expr1 && expr2, it will

  • Returns expr1 if it can be converted to false; otherwise, returns expr2.
  • Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.

See more on Expressions and operators

The obj.prop1 && obj.prop1.deepProp returns undefined because obj.prop1 is undefined which will be converted/coerced to false. The reason behind how JavaScript uses type coercion in Boolean contexts. You can read more, Truthy.

I often use the && to check If the property is actually existed before going down further.

//good
if (obj.prop1 && obj.prop1.deepProp) doSomething()

//error prone
if (obj.prop1.deepProp)
  //Uncaught TypeError: Cannot read property 'deepProp' of undefined
  doSomething()

It works well for small chains of properties, but getting ugly very soon If we are going too deep into a property.

var obj = {
  prop1: {},
}
let neededProperty = obj.prop1.deepProp.veryVeryDeepProp
//Uncaught TypeError: Cannot read property 'veryVeryDeepProp' of undefined

let deepProperty = obj.prop1 && obj.prop1.deepProp.veryDeepProp.veryVeryDeepProp
//Uncaught TypeError: Cannot read property 'veryDeepProp' of undefined
//Same error as above because prop1 is an object which will be coerced to true so that
//obj.prop1.deepProp.veryVeryDeepProp operand will be evaluated and throw and error

let safeProperty =
  obj.prop1 &&
  obj.prop1.deepProp &&
  obj.prop1.deepProp.veryDeepProp &&
  obj.prop1.deepProp.veryVeryDeepProp
//undefined
//This is a very safe check but the code will be messy.

2. Using try/catch blocks.

Because some things can go wrong…

try {
  let deepProperty =
    obj.prop1 && obj.prop1.deepProp.veryDeepProp.veryVeryDeepProp
} catch (exception) {
  // do something else
}

But placing many try/catch blocks throughout your code just to access properties is neither practical nor readable.

3. Helper function

We will write a simple helper function that does nothing else but calling a provided function in a try/catch block. With the support of ES6 Arrow function, we can call the helper function in just a one-line callback.

var obj = {}

function getSafe(fn) {
  try {
    return fn()
  } catch (e) {
    console.log(e)
    return undefined
  }
}

// use it like this
let deepProperty = getSafe(
  () => obj.prop1.deepProp.veryDeepProp.veryVeryDeepProp
)

uncaught type error

That way, you will either get the property value or undefined. That works because JavaScript only evaluates the content of the inner callback (or closure) when it is actually executed. So it will only be evaluated inside of the try/catch block and not yet in the code calling the helper function. This version down below will never work because the property argument will be evaluated when we pass it into the function.

var obj = {}

function getSafeNaive(property) {
  try {
    return property
  } catch (e) {
    return undefined
  }
}

let deepProperty = getSafeNaive(
  obj.prop1.deepProp.veryDeepProp.veryVeryDeepProp
)
//error from here, so that cannot go inside the try catch block

Elvis Operator

Some programming languages also support the so called elvis operator ?. that is yet another approach to the same problem. Applying it to the dirty example from above would like this obj?.prop1?.deepProp?.veryDeepProp?.veryVeryDeepProp. Essentially, it makes the compiler stop accessing more nested properties as soon as one of them is null (or undefined, or whatever null-type(s) that language uses).

Currently, there is no elvis operator in neither JavaScript nor TypeScript.


In Angular, there is the support elvis operator to protect against a view render failure. They call it safe navigation operator. Take the example below

The current person name is {{nullObject?.name}}

Since it is trying to access name property of a null value, the whole view disappears and you can see the error inside the browser console. It works perfectly with long property paths such as a?.b?.c?.d. So I recommend you to use it everytime you need to access a property inside a template.

TypeScript 3.7 - Optional Chaining

Detail Release Note

After a long wait, finally TypeScript has brought this feature to live. It basically is the elvis operator above.

At its core, optional chaining lets us write code where TypeScript can immediately stop running some expressions if we run into a null or undefined. The star of the show in optional chaining is the new ?. operator for optional property accesses. When we write code like

let x = foo?.bar.baz()

this is a way of saying that when foo is defined, foo.bar.baz() will be computed; but when foo is null or undefined, stop what we’re doing and just return undefined.”

let x = foo === null || foo === undefined ? undefined : foo.bar.baz()

Note that if bar is null or undefined, our code will still hit an error accessing baz. Likewise, if baz is null or undefined, we’ll hit an error at the call site. ?. only checks for whether the value on the left of it is null or undefined - not any of the subsequent properties.

You might find yourself using ?. to replace a lot of code that performs repetitive nullish checks using the && operator.

// Before
if (foo && foo.bar && foo.bar.baz) {
  // ...
}

// After-ish
if (foo?.bar?.baz) {
  // ...
}

Keep in mind that ?. acts differently than those && operations since && will act specially on “falsy” values (e.g. the empty string, 0, NaN, and, well, false), but this is an intentional feature of the construct. It doesn’t short-circuit on valid data like 0 or empty strings.

Published 22 Jan 2018

Recent Posts

Find a sequence to produce a number by adding 5 or multiplying by 3

Just read an interesting problem this morning. It seems not to be difficult

The combination of debounce and throttle

Debounce and throttle are two techniques to control how many times we allow a function to be executed over time


Follow @tuantrungvo on Twitter for more!