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 :)
Interested in Alpine.js?
Power up your debugging with the Alpine.js Devtools Extension for Chrome and Firefox. Trusted by over 15,000 developers (rated 4.5 ⭐️).
orJoin 1000s of developers learning about Enterprise-grade Node.js & JavaScript