(Updated: )
/ #javascript #web development 

Avoid null/undefined in JavaScript arrays

How to avoid TypeError: Cannot read property ___ of undefined using Array.filter(Boolean)

tl;dr: Array.filter(Boolean) filters out falsy values (null, undefined, 0, false, '') and avoids Cannot read property of undefined errors.

Table of contents:

Table of Contents

This was originally posted on 11th of April 2018, as the first post of the Code with Hugo blog

The original version is available on dev.to/hugo__df/avoiding-falsy-values-in-javascript-arrays

EDITS:

  • 13th December 2018 to improve readability and reach a wider audience.

An overview of the “Boolean” function/constructor

Boolean when passed any falsy value returns false and when passed a truthy value returns true, see the following:

Boolean(false); // false
Boolean(""); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(0); // false
Boolean(NaN); // false

Boolean(1); // true
Boolean("hello"); // true
Boolean(true); // true
Boolean({}); // true
Boolean([]); // true

A simple example of .filter(Boolean)

// Fun function that converts a name into a
// 4 all-cap letters display name
const makeDisplayName = name =>
  (name.charAt(0) + name.slice(1).replace(/a|e|i|o|u/g, ""))
    .toUpperCase()
    .slice(0, 4);

const displayNames = [null, "orange", "apple", "mango", undefined]
  .filter(Boolean)
  .map(makeDisplayName);
// [ 'ORNG', 'APPL', 'MNG' ]

// vs
const displayNamesErrors = [null, "orange", "apple", "mango", undefined].map(
  makeDisplayName
);
// TypeError: Cannot read property 'charAt' of undefined

How this works & caveats

Note that a valid use case of filtering out falsy values except 0 needs special treatment since, Boolean(0) returns false, hence:

const noFalsyEvenZero = [NaN, undefined, null, 0, 1, 2, 2000, Infinity].filter(
  Boolean
);
// [ 1, 2, 2000, Infinity ]
const noFalsyExceptZero = [
  NaN,
  undefined,
  null,
  0,
  1,
  2,
  2000,
  Infinity
].filter(el => el === 0 || Boolean(el));
// [ 0, 1, 2, 2000, Infinity ]

Situations in which “Cannot read property of undefined” would this occur

Usually this happens when you want to compute something over an Array of objects where some of the elements have a property but others don’t.

const companies = [
  {
    name: null,
    employees: [],
    founders: []
  },
  {
    name: "orange",
    employees: [],
    founders: []
  },
  {
    name: "apple",
    employees: [],
    founders: []
  },
  {
    name: "mango",
    employees: [],
    locations: []
  },
  {
    employees: [],
    founders: []
  }
];
const companyNames = companies.map(company => company.name);
// [undefined, "orange", "apple", "mango", undefined]

An issue can occur when you have null or undefined in your list

const makeDisplayName = name =>
  (name.charAt(0) + name.slice(1).replace(/a|e|i|o|u/g, ""))
    .toUpperCase()
    .slice(0, 4);

const companyDisplayNames = [null, "orange", "apple", "mango", undefined].map(
  makeDisplayName
);
// TypeError: Cannot read property 'charAt' of undefined

To avoid this we can filter falsy values out:

const makeDisplayName = name =>
  (name.charAt(0) + name.slice(1).replace(/a|e|i|o|u/g, ""))
    .toUpperCase()
    .slice(0, 4);

const companyDisplayNames = [null, "orange", "apple", "mango", undefined]
  .filter(Boolean) // the identity function: `item => item` would also work here :)
  .map(makeDisplayName);
// [ 'ORNG', 'APPL', 'MNG' ]
// No Error :)
Author

Hugo Di Francesco

Co-author of "Professional JavaScript", "Front-End Development Projects with Vue.js" with Packt, "The Jest Handbook" (self-published). Hugo runs the Code with Hugo website helping over 100,000 developers every month and holds an MEng in Mathematical Computation from University College London (UCL). He has used JavaScript extensively to create scalable and performant platforms at companies such as Canon, Elsevier and (currently) Eurostar.

Get The Jest Handbook (100 pages)

Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library.