Are you familiar with expressions like these:
a !== undefined && a !== null ? a : b
if (a.x === undefined || a.x === null) { a.x = b }
{ foo: foo, bar: bar }
a ? a.b : undefined
function getX(o) { return o.x }
What do they all have in common? They are highly verbose, and all have a nice shorthand alternatives. Let’s see how we can improve each one of these:
Nullish coalescing operator ??
This operator checks the value of the left hand-side operand – if it’s null or undefined, it returns the right hand-side operand. Otherwise it returns the left hand-side, without evaluating the right hand-side.
This allows simplifying the following expression:
To this:
Unlike || operator that checks for any falsy value, this operator only checks for nullish values – meaning null or undefined. Therefore it is safer to use in cases that a is a boolean which can be false or a number which can be 0, and then a || b will return the value of b
Nullish coalescing assignment ??=
This operator only evaluates the right operand and assigns to the left if the left operand is null or undefined.
So we can simplify this expression:
a.x = b
}
to this:
JSON shorthand syntax
The shorthand syntax was introduced with ES6 and is already pretty common.
Use it to shorten this:
const age = 32
const talk = text => void console.log(text)
const person = {
name: name,
age: age,
talk: talk
}
to that:
const age = 32
const talk = text => void console.log(text)
const person = {
name,
age,
talk
}
Optional chaining ?.
This operator accesses an object’s property just like . does. However, unlike ., if the object is null or undefined, the expression will return undefined instead of throwing an error.
This allows replacing this code:
with that:
This operator is pretty strong, and can be used in various ways:
Chaining: a?.b?.c?.d
Call interface method: someInterface.customMethod?.()
Note that in this case, if customMethod exists, but it is not a function, you’d still get an exception someInterface.customMethod is not a function
Access dynamic property with bracket notation: x?.[propname]
Access array items: array?.[50] – even if array is nullish, you’d get undefined instead of an exception
Arrow functions
There’s a lot to say about arrow functions, but in the context of this post I want to focus on a specific use – 1 liner methods that calculate something or access some property. They have 2 attributes that help with code shortening:
Arrow functions that do not have a block body wrapped with curly brackets {/*…*/} have an implicit return.
in a single-param arrow function you do not have to put the argument in parentheses
Meaning, you can change this:
return o.x
}
with this
This is super useful, for example, for mapping functions.
Note that there are some caveats though:
Arrow functions do not have this
Arrow functions do not have arguments. You can use spread operator instead. E.g (…args) => args[0]
Arrow functions cannot call super or be used as constructors