Avoid null/undefined in JavaScript arrays
How to avoid
TypeError: Cannot read property ___ of undefined
usingArray.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 :)
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.
orJoin 1000s of developers learning about Enterprise-grade Node.js & JavaScript