37
loading...
This website collects cookies to deliver better user experience
There are only two hard things in Computer Science: cache invalidation and naming things.
if (item.group === 'fruits' && item.name === 'apple' && item.status === 'ripe') {
// slice my apple
}
const isAppleRipe = item.group === 'fruits' && item.name === 'apple' && item.status === 'ripe';
if (isAppleRipe) {
// slice my apple
}
!
and !!
(single and double exclamation). This is especially useful when writing Typescript that are type sensitive when return values.const list = [];
const isEmpty = !list.length;
const isNotEmpty = !!list.length;
if (!isAvailable) {
// do your thing
}
// instead of
if (isAvailable === null || isAvailable === undefined || isAvailable === false) {
// do your thing
}
function doYourThing = (isActive) => {
if (isActive !== null || isActive !== undefined || isActive !== false) {
...
}
}
function doYourThing = (isActive: boolean = false) => {
if (isActive) {
...
}
}
item && item.name
to avoid nullish reference error. We can now use optional chaining when checking for object property, which would return undefined
if it is not available.if (item && item.name) { ... }
if (!!item?.name) { ... }
function getUserSession(user) {
if (!!user.name && !!user.password) {
// proceed to get user session
}
}
function getUserSession(user) {
if (!user.name || !user.password) {
return;
}
// proceed to get user session
}
if else
statements that are hard to read and hard to edit.let itemGroup;
if (itemType === 'apple') {
itemGroup = 'fruit';
} else {
itemGroup = 'vegetable';
}
const itemGroup = itemType === 'apple' ? 'fruit' : 'vegetable';
||
operator. If we want to be more explicit with our checking, to target only null
or undefined
we can use nullish coalescing operator.const itemNameFalsyCheck = item.name || 'Name is falsy';
const itemNameNullOrUndefinedCheck = item.name ?? 'Name is null or undefined';
.includes
or Set method .has
instead of chaining multiple OR operators.const isFruit = (item.type === 'apple' || item.type === 'orange' || item.type === 'durian');
if (isFruit) { ... }
const isFruit = ['apple', 'orange', 'durian'].includes(item.type);
// or
const isFruit = new Set(['apple', 'orange', 'durian']).has(item.type);
Set.has
has a significant performance edge over Array.includes
, especially when dealing with a large data set, it is worth fitting Set checking in your code when possible.Array.includes
.const listOfFruits = list.filter(x => {
const fruits = new Set(['apple', 'orange', 'durian']);
return fruits.has(x);
});
const listOfFruits = list.filter(x => ['apple', 'orange', 'durian'].includes(x));
Array.some
:const hasFruits = list.some(x => x.type === 'fruit');
Array.every
:const itsAllFruits = list.every(x => x.type === 'fruit');
if else
statement. It is in fact best to avoid multiple if else
as it is notoriously hard to read, hard to edit, and also slower in performance in comparison to the few options that we have. They are namely, switch
statements, object
literals, and Map
.let itemGroup;
if (item.name === 'apple') {
itemGroup = 'fruit';
} else if (item.name === 'carrot') {
itemGroup = 'vegetable';
} else if (item.name === 'mazda') {
itemGroup = 'car';
} else {
itemGroup = 'fruit';
}
let itemGroup;
// with switch
switch (item.name) {
case 'carrot':
itemGroup = 'vegetable';
return;
case 'mazda':
itemGroup = 'car';
return;
case 'apple':
default:
itemGroup = 'fruit';
return;
}
// with object
itemGroup = {
apple: 'fruit',
carrot: 'vegetable',
mazda: 'car'
}[item.type] ?? 'fruit';
// with Map
itemGroup = Map()
.set('apple', 'fruit')
.set('carrot', 'vegetable')
.set('mazda', 'car')
.get(item.type) ?? 'fruit';
const itemGroup = ((type) => {
case 'carrot':
return 'vegetable';
case 'mazda':
return 'car';
case 'apple':
default:
return 'fruit';
})(item.type);