tl;dr : use Array.filter(Boolean)
to filter out falsy values and avoid errors.
// 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
Boolean
when passed any falsy value returns false
and when passed a truthy value returns true
:
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
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 this 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 :)
Originally published at codewithhugo.com on April 11, 2018.