This tutorials explains about fixing an error , an feature of Optional Chaining Operator.

TypeError: Cannot read property ‘’ of undefined

javascript nested object undefined or null check

A nested object is an object nested inside an object with a deep level. Each object contains properties. Let’s see an example to check nullish values against deeply nested properties in the current javascript implementation.

const employee = {
  name: 'Franc',
  department: {
    name: 'sales'
  }
};
const name = employee.name;
console.log(name); // Franc
const department = employee.department;
console.log(department);// {name:'sales'}
const departmentName = employee.department.name;
console.log(departmentName); //sales

console.log(employee.salary) //undefined
console.log(employee.department.supervisor) // undefined

In the above example, Create an object with nested properties.

accessing object with valid properties (name, department, and department. name) returning valid values.

Accessing non existing properties (employee.salary, employee.department.supervisor) in objects returns `undefined'.

Accessing nested properties on an undefined object () throws an error -TypeError: Cannot read property 'name' of undefined as seen in the below example.

console.log(employee.department.supervisor.name)

we have to handle null or undefined values using if-else conditional expression and fallback to else block to avoid these errors.

if ((employee)
  && (employee.department)
    && (employee.department.supervisor)
      && (employee.department.supervisor.name)) {
          console.log(employee.department.supervisor.name)
          }
  else {
    console.log('department supervisor name not found');
    }

And output is

department supervisor name not found

Code looks not simple and needs to write a lot of code and is difficult to readability to handle deeply nested objects with more levels.

The same can be rewritten using the ternary operator.

const deptname =
  (employee
    ? (employee.department
      ? (employee.department.supervisor
        ? employee.department.supervisor.name
        : undefined)
      : undefined)
    : undefined);
  console.log(deptname)// undefined

With ES11, The null and undefined handling is simplified by introducing the Optional Chaining Operator.

Let’s look into a new feature in ES11.

Es11 features- Optional Chaining Operator

Optional Chaining operator is the latest feature introduced with ‘ES2020’ to the latest javascript. and its symbol is ?. ie single question mark and dot.

This operator allows finding the nested object properties without checking the reference of each nested object property. This operator enables to return of undefined or fallback value if any reference is nullish values - null or undefined.

Advantages

  • This looks simple and has less coding
  • Human readability to avoid error-prone
  • useful to avoid errors.

This will be useful for default to fallback value when deeply object properties are null or undefined. It is a Short circuit operator that applies two expressions, and returns its value of

  • right-hand expression is not processed when the left-hand expression evaluated is null or undefined.
  • left-hand operand value when the left-hand operand is not null or undefined Syntax
Object?.property
Object?.[expresson]
array?.[index]
function?.(args)

The syntax contains question marks with dot operators. There are many variations of using the Optional Chaining operator.

  • Object?.property - check Static property
  • Object?.[expresson] - Check Dynamic property
  • array?.[index] - Check array index values
  • function?.(args) - Checking in function calls

For example, given a deeply nested object (employe.department.name), check for null or undefined values for the name property.

let departmentName=employe.department && employe.department.name;

Rewriting using optional chain operator

let deparmentName=employe.department?.name

Variables are added to the hash symbol to make it for private use in a class. Syntax

#variable

Let’s see an example.

const result1 = null ?? "default1";
const result2 = "" ?? "default2";
const result2 = 11 ?? 0;

console.log(result1); // default1
console.log(result2); // default2, Empty string is not equal to null or undefined
console.log(result2); // 11

Optional Chaining in Typescript example

Optional Chaining operator introduced in Typescript 3.7 language.

This will be useful for checking the response from consuming API calls Consider API calls that return the nested deep response object.

const result = response.employe.department.id;

if an employee or department is null or undefined, It throws an error TypeError: Cannot read property ’employe’ of undefined. To avoid these errors, have to validation check as per below.

let id;
if (response.employe && response.employe.department) {
  id = response.employe.department.id;
}else{
   id="Id not found"
}

so id always has value either valid value or default fallback value. To avoid this length code check, the nullish coalescing operator, and optional chaining simplified this and error-prone.

const id = response.employe?.department?.id ?? "Id not found.";

compare with Ternary operator

We already have the Ternary operator - ?.

Optional ChaningTernary Operatordescription
object?.value1object == null ? undefined : object?.value1if object is null or undefined, returns undefined,else returns object.value1
object?.[name]object == null ? undefined : object[name]returns object[name] if nullish else undefined
object?.function()object == null ? undefined : object.function()calls object.function() if not nullish,else return undefined, error if not function

Option chaining properties can be used in short-circuit, long short-circuit, and stacking operations.

Browser Support

This feature supports the following browser versions.

  • Chrome 80+
  • Firefox’s latest version
  • Safari’s latest version
  • Babel plugin

Babel plugin-proposal-optional-chaining

To install this feature nodejs applications, Please add plugin-proposal-optional-chaining as devDependencies.

npm install --save-dev @babel/plugin-proposal-optional-chaining

configure .babelrc file by adding plugins entry as follow

{
  "plugins": ["@babel/plugin-proposal-optional-chaining"]
}