Editor’s note: This guide to the most useful JavaScript and TypeScript shorthands was last updated on 3 January 2023 to address errors in the code and include information about the satisfies operator introduced in TypeScript v4.9.
JavaScript and TypeScript share a number of useful shorthand alternatives for common code concepts. Shorthand code alternatives can help reduce lines of code, which is something we typically strive for.
In this article, we will review 18 common JavaScript and TypeScript and shorthands. We will also explore examples of how to use these shorthands.
Read through these useful JavaScript and TypeScript shorthands or navigate to the one you’re looking for in the list below.
Jump ahead:
Array.indexOf
shorthand using the bitwise operator!!
Using shorthand code is not always the right decision when writing clean and scalable code. Concise code can sometimes be more confusing to read and update. So, it is important that your code is legible and conveys meaning and context to other developers.
Our decision to use shorthands must not be detrimental to other desirable code characteristics. Keep this in mind when using the following shorthands for expressions and operators in JavaScript and TypeScript.
All shorthands available in JavaScript are available in the same syntax in TypeScript. The only slight differences are in specifying the type in TypeScript, and the TypeScript constructor shorthand is exclusive to TypeScript.
The ternary operator is one of the most popular shorthands in JavaScript and TypeScript. It replaces the traditional if…else
statement. Its syntax is as follows:
[condition] ? [true result] : [false result]
The following example demonstrates a traditional if…else
statement and its shorthand equivalent using the ternary operator:
// Longhand const mark = 80 if (mark >= 65) { return "Pass" } else { return "Fail" } // Shorthand const mark = 80 return mark >= 65 ? "Pass" : "Fail"
The ternary operator is great when you have single-line operations like assigning a value to a variable or returning a value based on two possible conditions. Once there are more than two outcomes to your condition, using
if/else
blocks are much easier to read.
Another way to replace an if…else
statement is with short-circuit evaluation. This shorthand uses the logical OR operator ||
to assign a default value to a variable when the intended value is falsy.
The following example demonstrates how to use short-circuit evaluation:
// Longhand let str = '' let finalStr if (str !== null && str !== undefined && str != '') { finalStr = str } else { finalStr = 'default string' } // Shorthand let str = '' let finalStr = str || 'default string' // 'default string
This shorthand is best used when you have a single-line operation and your condition depends on the falseness or non-falseness of a value/statement.
The nullish coalescing operator ??
is similar to short-circuit evaluation in that it assigns a variable a default value. However, the nullish coalescing operator only uses the default value when the intended value is also nullish.
In other words, if the intended value is falsy but not nullish, it will not use the default value.
Here are two examples of the nullish coalescing operator:
// Longhand let str = '' let finalStr if (str !== null && str !== undefined) { finalStr = 'default string' } else { finalStr = str } // Shorthand let str = '' let finaStr = str ?? 'default string' // ''
// Longhand let num = null let actualNum if (num !== null && num !== undefined) { actualNum = num } else { actualNum = 0 } // Shorthand let num = null let actualNum = num ?? 0 // 0
This is similar to the nullish coalescing operator by checking that a value is nullish and has added the ability to assign a value following the null check.
The example below demonstrates how we would check and assign in longhand and shorthand using the logical nullish assignment:
// Longhand let num = null if (num === null) { num = 0 } // shorthand let num = null num ??= 0
JavaScript has several other assignment shorthands like addition assignment
+=
, multiplication assignment*=
, division assignment/=
, remainder assignment%=
, and several others. You can find a full list of assignment operators here.
Template literals, which was introduced as part of JavaScript’s powerful ES6 features, can be used instead of +
to concatenate multiple variables within a string. To use template literals, wrap your strings in ``
and variables in ${}
within those strings.
The example below demonstrates how to use template literals to perform string interpolation:
// Longhand const name = 'Iby' const hobby = 'to read' const fullStr = name + ' loves ' + hobby // 'Iby loves to read' // Shorthand const name = 'Iby' const hobby = 'to read' const fullStr = `${name} loves ${hobby}` // 'Iby loves to read'
You can also use template literals to build multi-line strings without using \n
. For example:
// Shorthand const name = 'Iby' const hobby = 'to read' const fullStr = `${name} loves ${hobby}. She also loves to write!`
Using template literals is helpful for adding strings whose values may change into a larger string, like HTML templates. They are also useful for creating multi-line string because string wrapped in template literals retain all white spacing and indentation.
In JavaScript and TypeScript, you can assign a property to an object in shorthand by mentioning the variable in the object literal. To do this, the variable must be named with the intended key.
See an example of the object property assignment shorthand below:
// Longhand const obj = { x: 1, y: 2, z: 3 }
// Shorthand const x = 8 const y = 10 const obj = { x, y }
Dot notation allows us to access the keys or values of an object. With optional chaining, we can go a step further and read keys or values even when we are not sure whether they exist or are set.
When the key does not exist, the value from optional chaining is undefined
. This helps us avoid unneeded if/else
check conditions when reading values from objects and unnecessary try/catch
to handle errors thrown from trying to access object keys that don’t exist.
See an example of optional chaining in action below:
// Longhand const obj = { x: { y: 1, z: 2 }, others: [ 'test', 'tested' ] } if (obj.hasProperty('others') && others.length >= 2) { console.log('2nd value in others: ', obj.others[1]) }
// Shorthand const obj = { x: { y: 1, z: 2 }, others: [ 'test', 'tested' ] } console.log('2nd value in others: ', obj.others?.[1]) // 'tested' console.log('3rd value in others: ', obj.others?.[2]) // undefined
Besides the traditional dot notation, another way to read the values of an object is by destructuring the object’s values into their own variables.
The following example demonstrates how to read the values of an object using the traditional dot notation compared to the shorthand method using object destructuring:
// Longhand const obj = { x: { y: 1, z: 2 }, other: 'test string' } console.log('Value of z in x: ', obj.x.z) console.log('Value of other: ', obj.other) // Shorthand const obj = { x: { y: 1, z: 2 }, other: 'test string' } const {x, other} = obj const {z} = x console.log('Value of z in x: ', z) console.log('Value of other: ', other) You can also rename the variables you destructure from the object. Here's an example: const obj = {x: 1, y: 2} const {x: myVar} = object console.log('My renamed variable: ', myVar) // My renamed variable: 1
The spread operator …
is used to access the content of arrays and objects. You can use the spread operator to replace array functions, like concat
, and object functions, like object.assign
.
Review the examples below to see how the spread operator can replace longhand array and object functions:
// Longhand const arr = [1, 2, 3] const biggerArr = [4,5,6].concat(arr) const smallObj = {x: 1} const otherObj = object.assign(smallObj, {y: 2}) // Shorthand const arr = [1, 2, 3] const biggerArr = [...arr, 4, 5, 6] const smallObj = {x: 1} const otherObj = {...smallObj, y: 2}
The traditional JavaScript for
loop syntax is as follows:
for (let i = 0; i < x; i++) { … }
We can use this loop syntax to iterate through arrays by referencing the array length for the iterator. There are three for
loop shorthands that offer different ways to iterate through an array object:
for…of
: To access the array entriesfor…in
: To access the indexes of an array and the keys when used on an object literalArray.forEach
: To perform operations on the array elements and their indexes using a callback functionPlease note, Array.forEach
callbacks have three possible arguments, which are called in this order:
The examples below demonstrate these object loop shorthands in action:
// Longhand const arr = ['Yes', 'No', 'Maybe'] for (let i = 0; i < arr.length; i++) { console.log('Here is item: ', arr[i]) } // Shorthand const arr = ['Yes', 'No', 'Maybe'] for (let str of arr) { console.log('Here is item: ', str) } arr.forEach((str) => { console.log('Here is item: ', str) }) for (let index in arr) { console.log(`Item at index ${index} is ${arr[index]}`) } // For object literals const obj = {a: 1, b: 2, c: 3} for (let key in obj) { console.log(`Value at key ${key} is ${obj[key]}`) }
Array.indexOf
shorthand using the bitwise operatorWe can look up the existence of an item in an array using the Array.indexOf
method. This method returns the index position of the item if it exists in the array and returns -1
if it does not.
In JavaScript, 0
is a falsy value, while numbers less than or greater than 0
are considered truthy. Typically, this means we need to use an if…else
statement to determine if the item exists using the returned index.
Using the bitwise operator ~
instead of an if…else
statement allows us to get a truthy value for anything greater than or equal to 0
.
The example below demonstrates the Array.indexOf
shorthand using the bitwise operator instead of an if…else
statement:
const arr = [10, 12, 14, 16] const realNum = 10 const fakeNum = 20 const realNumIndex = arr.indexOf(realNum) const noneNumIndex = arr.indexOf(fakeNum) // Longhand if (realNumIndex > -1) { console.log(realNum, ' exists!') } else if (realNumIndex === -1) { console.log(realNum, ' does not exist!') } if (noneNumIndex > -1) { console.log(fakeNum, ' exists!') } else if (noneNumIndex === -1) { console.log(fakeNum, ' does not exist!') } // Shorthand const arr = [10, 12, 14, 16] const realNum = 10 const fakeNum = 20 const realNumIndex = arr.indexOf(realNum) const noneNumIndex = arr.indexOf(fakeNum) console.log(realNum + (~realNumIndex ? ' exists!' : ' does not exist!') console.log(fakeNum + (~noneNumIndex ? ' exists!' : ' does not exist!')
!!
In JavaScript, we can cast variables of any type to a Boolean value using the !![variable]
shorthand.
See an example of using the !! [variable]
shorthand to cast values to Boolean
:
// Longhand const simpleInt = 3 const intAsBool = Boolean(simpleInt) // Shorthand const simpleInt = 3 const intAsBool = !!simpleInt
Functions in JavaScript can be written using arrow function syntax instead of the traditional expression that explicitly uses the function
keyword. Arrow functions are similar to lambda functions in other languages.
Take a look at this example of writing a function in shorthand using an arrow function expression:
// Longhand function printStr(str) { console.log('This is a string: ', str) } printStr('Girl!') // Shorthand const printStr = (str) => { console.log('This is a string: ', str) } printStr('Girl!') // Shorthand TypeScript (specifying variable type) const printStr = (str: string) => { console.log('This is a string: ', str) } printStr('Girl!')
In JavaScript, we typically use the return
keyword to return a value from a function. When we define our function using arrow function syntax, we can implicitly return a value by excluding braces {}
.
For multi-line statements, such as expressions, we can wrap our return expression in parentheses ()
. The example below demonstrates the shorthand code for implicitly returning a value from a function using an arrow function expression:
// Longhand function capitalize(name) { return name.toUpperCase() } function add(numA, numB) { return numA + numB } // Shorthand const capitalize = (name) => name.toUpperCase() const add = (numA, numB) => (numA + numB) // Shorthand TypeScript (specifying variable type) const capitalize = (name: string) => name.toUpperCase() const add = (numA: number, numB: number) => (numA + numB)
In JavaScript, we typically access mathematical functions and constants using the built-in Math
object. Some of those functions are Math.floor()
, Math.round()
, Math.trunc()
, and many others.
The Math.trunc()
(available in ES6) returns the integer part. For example, number(s) before the decimal of a given number achieves this same result using the Double bitwise NOT operator ~~
.
Review the example below to see how to use the Double bitwise NOT operator as a Math.trunc()
shorthand:
// Longhand const num = 4.5 const floorNum = Math.trunc(num) // 4 // Shorthand const num = 4.5 const floorNum = ~~num // 4
It is important to note that the Double bitwise NOT operator
~~
is not an official shorthand forMath.trunc
because some edge cases do not return the same result. More details on this are available here.
Another mathematical function with a useful shorthand is the Math.pow()
function. The alternative to using the built-in Math
object is the **
shorthand.
The example below demonstrates this exponent power shorthand in action:
// Longhand const num = Math.pow(3, 4) // 81 // Shorthand const num = 3 ** 4 // 81
There is a shorthand for creating a class and assigning values to class properties via the constructor in TypeScript. When using this method, TypeScript will automatically create and set the class properties. This shorthand is exclusive to TypeScript alone and not available in JavaScript class definitions.
Take a look at the example below to see the TypeScript constructor shorthand in action:
// Longhand class Person { private name: string public age: int protected hobbies: string[] constructor(name: string, age: int, hobbies: string[]) { this.name = name this.age = age this.hobbies = hobbies } } // Shorthand class Person { constructor( private name: string, public age: int, protected hobbies: string[] ) {} }
The satisfies operator gives some flexibility from the constraints of setting a type with the error handling covering having explicit types.
It is best used when a value has multiple possible types. For example, it can be a string or an array; with this operator, we don’t have to add any checks. Here’s an example:
// Longhand type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette: Record<Colors, string | RGB> = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] }; if (typeof palette.red !== 'string') { console.log(palette.red.at(0)) } // shorthand type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] } satisfies Record<Colors, string | RGB>; console.log(palette.red.at(0))
In the longhand version of our example above, we had to do a typeof
check to make sure palette.red
was of the type RGB
and that we could read its first property with at
.
While in our shorthand version, using satisfies
, we don’t have the type restriction of palette.red
being string
, but we can still tell the compiler to make sure palette
and its properties have the correct shape.
The
Array.property.at()
i.e.,at()
method, accepts an integer and returns the item at that index.Array.at
requiresES2022
target, which is available from TypeScript v4.6 onwards. More information is available here.
These are just a few of the most commonly used JavaScript and TypeScript shorthands.
JavaScript and TypeScript longhand and shorthand code typically work the same way under the hood, so choosing shorthand usually just means writing less lines of code. Remember, using shorthand code is not always the best option. What is most important is writing clean and understandable code that other developers can read easily.
What are your favorite JavaScript or TypeScript shorthands? Share them with us in the comments!
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
8 Replies to "18 JavaScript and TypeScript shorthands to know"
Hello !
Thanks you for your article, I learn a lot with it.
But I think that I found a mistake in short circuit evaluation. When you show the traditional version with if…else statement you use logical && operator but I think you wanted use logical || operator.
I think that is just a wrting error but i prefer tell it to you.
Have a good day
Hi Romain thank you for spotting that! I’ll fix it right away
I was avoiding using logical OR to make clear the explanation of short circuit evaluation, so the if statement should be confirming “str” has a valid value. I have switched the assignment statements in the condition so it is correct now.
I think there is an error in the renamed variable of destructured object. Shouldn’t the line
const {x: myVar} = object
be:
const {x: myVar} = obj
This code doesn’t work in Typescript?
// for object literals
const obj2 = {
a: 1,
b: 2,
c: 3
}
for (let keyLetter in obj2) {
console.log(`key: ${keyLetter} value: ${obj2[keyLetter]}`);
Gets error:
error: TS7053 [ERROR]: Element implicitly has an ‘any’ type because expression of type ‘string’ can’t be used to index type ‘{ 0: number; 1: number; 2: number; }’.
No index signature with a parameter of type ‘string’ was found on type ‘{ 0: number; 1: number; 2: number; }’.
console.log(`key: ${keyLetter} value: ${obj2[keyLetter]}`);
Awesome information, thanks for sharing!!! 🚀🚀🚀
Good List of useful operators
~~x is not the same as Math.floor(x) : try it on negative numbers. You’ll find that ~~ is the same as Math.trunc(x) instead.