Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

How to Check If Function Returns a Promise in JavaScript

To check if a function returns a Promise in JavaScript, call the function (impossible without doing so), and use the instanceof operator to check if the return value is a Promise object.

For example:

JavaScript
console.log(returnsPromise(func1)); console.log(returnsPromise(func2)); console.log(returnsPromise(func3)); function returnsPromise(func) { return func() instanceof Promise; } function func1() { return new Promise((resolve) => { resolve('Coding Beauty'); }); } async function func2() { return 100; } function func3() { return 'Coding Beauty'; }

Unfortunately, there’s no way to check if a function returns a Promise without invoking it and getting its result.

After getting the return value, we use instanceof to check if it’s a Promise instance.

Ensure Promise return value from function

If you’re checking the function’s return value to convert a possible non-Promise value to a Promise, you can simply wrap the function call in the Promise.resolve() method.

If the function’s return value is a Promise, Promise.resolve() will return that Promise object.

If the function’s return value is not a Promise, Promise.resolve() will return a Promise that will resolve that return value directly.

JavaScript
Promise.resolve(func1()).then((value) => { console.log(value); // Coding Beauty }); Promise.resolve(func2()).then((value) => { console.log(value); // JavaScript; }); // does return Promise function func1() { return new Promise((resolve) => { resolve('Coding Beauty'); }); } // does NOT return Promise function func2() { return 'JavaScript'; }

Check if function is async

It’s also possible to check if a function is async, by checking if the constructor.name property of the function is 'AsyncFunction':

JavaScript
console.log(isAsync(func1)); // false console.log(isAsync(func2)); // true console.log(isAsync(func3)); // false function isAsync(func) { return func.constructor.name === 'AsyncFunction'; } // NOT async, but returns Promise function func1() { return new Promise((resolve) => { resolve('Coding Beauty'); }); } // async, returns Promise too async function func2() { return 100; } // NOT async, returns NON-Promise function func3() { return 'Coding Beauty'; }

Almost every object in JavaScript has a constructor property that returns a Function reference to the constructor function that created the object instance.

JavaScript
const num = 2; const promise = new Promise((resolve) => resolve(100)); const arr = []; const asyncFunc = async () => 'Coding Beauty'; console.log(num.constructor); // [Function: Number] console.log(promise.constructor); // [Function: Promise] console.log(arr.constructor); // [Function: Array] console.log(asyncFunc.constructor); // [Function: AsyncFunction]

After getting the constructor, we use the Function instance name property to get the name of the function.

JavaScript
console.log(num.constructor.name); // Name console.log(promise.constructor.name); // Promise console.log(arr.constructor.name); // Array console.log(asyncFunc.constructor.name); // AsyncFunction

Note that this approach is not very reliable as the value of constructor.name is not fixed. It could easy be changed in a user-defined class to any value, including 'AsyncFunction':

JavaScript
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } static name = 'AsyncFunction' } const person = new Person('Brandon', 'Evans'); console.log(isAsync(person)); // true (?!) function isAsync(func) { return func.constructor.name === 'AsyncFunction'; }

How to Check if a Variable is a String in JavaScript

To check if a variable is a string in JavaScript, use the typeof operator, i.e., if (typeof variable === 'string'). If the typeof variable returns 'string', then the variable is a string. Otherwise, it is not a string.

For example:

JavaScript
const variable = 'Coding Beauty'; if (typeof variable === 'string') { // 👇 this runs console.log('Variable is string'); } else { console.log('Variable is not string'); }

The typeof operator returns a string that indicates the type of its operand. For primitives, it returns the exact type, e.g., 'number', 'boolean', 'string', etc, for functions, it returns ‘function‘, and for complex or user-defined types, it returns 'object'.

JavaScript
console.log(typeof true); // 'boolean' console.log(typeof 'Coding Beauty'); // 'string' console.log(typeof 100); // 'number' console.log(typeof new Promise(() => {})); // 'object' console.log(typeof function () {}); // 'function' console.log(typeof Symbol()); // 'symbol' console.log(typeof (() => {})); // 'function' console.log(typeof []); // 'object' console.log(typeof {}); // 'object' console.log(typeof undefined); // 'undefined'

typeof undeclared_variable is 'undefined'?

Note that if you mistakenly use typeof on a variable that hasn’t been declared, typeof will not throw an error:

JavaScript
if (typeof undeclared === 'string') { console.log('Variable is string'); } else { console.log('Variable is NOT string'); }

When used on variables that haven’t been declared, typeof returns the string 'undefined':

JavaScript
console.log(typeof undeclared); // 'undefined'

typeof for string wrapper objects

The one instance where typeof won’t work is when the string was created as a wrapper object i.e., using the String() constructor with the new operator.

For such strings, it will return the 'object' string, instead of 'string'.

JavaScript
const strObj = new String('Coding Beauty'); console.log(typeof strObj); // 'object'

However, it’s not a good practice to use wrapper objects, as they serve no use. Wrapper objects are only used internally; when JavaScript auto-boxes a primitive value into an object to access a property on that object.

typeof null is 'object'?

Note that when typeof is used on the null value, it returns the string 'object'

JavaScript
console.log(typeof null) // 'object'

This is because, as stated in the MDN documentation:

In the first implementation of JavaScript, JavaScript values were represented as a type tag and a value. The type tag for objects was 0null was represented as the NULL pointer (0x00 in most platforms). Consequently, null had 0 as type tag, hence the typeof return value "object". (reference)

A fix was proposed for ECMAScript (via an opt-in), but was rejected. It would have resulted in typeof null === "null".

typeof NaN is 'number'?

Also, typeof NaN results in 'number':

JavaScript
console.log(typeof NaN); // 'number'

Because as stated in this StackOverflow answer and the spec, NaN is considered a numeric type in JavaScript.

How to Convert CSV to XML in JavaScript

We can use the csv-to-xml library available on NPM to quickly convert any CSV string to XML in JavaScript.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `color,maxSpeed,age red,120,2 blue,100,3 green,130,2`; const xml = csvToXml(csv); console.log(xml);

This code will produce the following output:

Output (XML)
<row> <color>red</color> <maxSpeed>120</maxSpeed> <age>2</age> </row> <row> <color>blue</color> <maxSpeed>100</maxSpeed> <age>3</age> </row> <row> <color>green</color> <maxSpeed>130</maxSpeed> <age>2</age> </row>

The default export function, csvToXml(), takes CSV data in a string and returns its equivalent XML representation.

csv-to-xml is an ES module that can work both in Node.js and browser environments.

Install csv-to-xml

Before using csv-to-xml, you’ll need to install your project. You can do this with the NPM or Yarn CLI.

Shell
npm i csv-to-xml # Yarn yarn add csv-to-xml

After installation, you’ll be able to import it into a JavaScript module, like this:

JavaScript
import csvToXml from 'csv-to-xml';

csvToXml() function

The primary function of this package is the csvToXml() function. It takes a string containing CSV data, converts it to XML, and returns the result as a string.

csvToXml() has two parameters:

  1. csvString: The string containing the CSV data.
  2. options: An object with option properties that control how the CSV is converted to the XML.
JavaScript
const xml = csvToXml(csv, { header: false, quote: 'single' });

Customize conversion of CSV to XML

The option parameter of the csvToXml() function lets you specify options to customize the CSV-to-XML conversion process.

rowName option

One such option is rowName, which lets you set the tag name used for the XML elements that each represent a row.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `color,maxSpeed,age red,120,2 blue,100,3 green,130,2`; const xml = csvToXml(csv, { rowName }); console.log(xml);
XML Output
<car> <color>red</color> <maxSpeed>120</maxSpeed> <age>2</age> </car> <car> <color>blue</color> <maxSpeed>100</maxSpeed> <age>3</age> </car> <car> <color>green</color> <maxSpeed>130</maxSpeed> <age>2</age> </car>

Now each XML row element is named car instead of the default row.

headerList option

There’s also headerList, an option used to set the CSV headers used for the conversion.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `First Name, Last Name, Location Alexander,Hill,Los Angeles Brandon,Evans,Paris Mike,Baker,London`; const xml = csvToXml(csv, { rowName: 'person', headerList: ['firstName', 'lastName', 'location'], }); console.log(xml);
XML Output
<person> <firstName>Alexander</firstName> <lastName>Hill</lastName> <location>Los Angeles</location> </person> <person> <firstName>Brandon</firstName> <lastName>Evans</lastName> <location>Paris</location> </person> <person> <firstName>Mike</firstName> <lastName>Baker</lastName> <location>London</location> </person>

header option

headerList is especially useful when the CSV data has no header row, and you see the header option to false to indicate this to the converter.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `Alexander,Hill,Los Angeles Brandon,Evans,Paris Mike,Baker,London`; const xml = csvToXml(csv, { rowName: 'user', headerList: ['fName', 'lName', 'city'], header: false, }); console.log(xml);
XML Output
<user> <fName>Alexander</fName> <lName>Hill</lName> <city>Los Angeles</city> </user> <user> <fName>Brandon</fName> <lName>Evans</lName> <city>Paris</city> </user> <user> <fName>Mike</fName> <lName>Baker</lName> <city>London</city> </user>

If header is false, and header names are not set with headerList, a default column name will be used. The name takes the format col{n} where {n} is the position of the column within its row.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `Alexander,Hill,Los Angeles Brandon,Evans,Paris Mike,Baker,London`; const xml = csvToXml(csv, { header: false, }); console.log(xml);
XML Output
<row> <col1>Alexander</col1> <col2>Hill</col2> <col3>Los Angeles</col3> </row> <row> <col1>Brandon</col1> <col2>Evans</col2> <col3>Paris</col3> </row> <row> <col1>Mike</col1> <col2>Baker</col2> <col3>London</col3> </row>

quote option

Another important option is quote, which lets you group data containing a comma (or some other separator) as a single column.

For example:

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `"Hill, A.",Los Angeles "Evans, B.",Paris "Baker, M.",London`; const xml = csvToXml(csv, { header: false, headerList: ['name', 'location'], quote: 'double', // Ignore comma in double quotes }); console.log(xml);
XML Output
<row> <name>Hill, A.</name> <location>Los Angeles</location> </row> <row> <name>Evans, B.</name> <location>Paris</location> </row> <row> <name>Baker, M.</name> <location>London</location> </row>

indentation option

With the indentation option, we can control how many spaces are used to indent child XML elements in the output. By default it’s 4, but we can set it to another numeric value, or a string like '\t'.

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `Alexander,Hill,Los Angeles Brandon,Evans,Paris Mike,Baker,London`; const xml = csvToXml(csv, { header: false, indentation: 2, }); console.log(xml);
XML Output
<row> <col1>Alexander</col1> <col2>Hill</col2> <col3>Los Angeles</col3> </row> <row> <col1>Brandon</col1> <col2>Evans</col2> <col3>Paris</col3> </row> <row> <col1>Mike</col1> <col2>Baker</col2> <col3>London</col3> </row>

separator option

Sometimes a character other than a comma is used to separate the columns. The separator option helps indicate this to the converter:

JavaScript
import csvToXml from 'csv-to-xml'; const csv = `color;maxSpeed;age red;120;2 blue;100;3 green;130;2`; const xml = csvToXml(csv, { separator: ';' }); console.log(xml);
XML Output
<row> <color>red</color> <maxSpeed>120</maxSpeed> <age>2</age> </row> <row> <color>blue</color> <maxSpeed>100</maxSpeed> <age>3</age> </row> <row> <color>green</color> <maxSpeed>130</maxSpeed> <age>2</age> </row>

Find a full list of options in the csv-to-xml homepage.

Native conversion of CSV to XML

It’s also possible to convert CSV data to XML without using any third-party libraries. Here’s how we can do it:

JavaScript
const csv = `color,maxSpeed,age red,120,2 blue,100,3 green,130,2`; const xml = csvToXml(csv); console.log(xml); function csvToXml(csvString) { const csvRows = csvString.split('\n').map((row) => row.trim()); // e.g., 'maxSpeed,color,age' -> ['maxSpeed', 'color', 'age'] const headers = csvRows[0].split(','); let xml = ''; // loop through each CSV row, csvRows[i] contains the row string for (let i = 1; i < csvRows.length; i++) { // e.g., 'blue,100,3' -> ['maxSpeed', 'color', 'age'] const details = csvRows[i].split(','); xml += `<row>\n`; for (let j = 0; j < headers.length; j++) { // e.g., <color>blue</color> xml += `<${headers[j]}>${details[j]}</${headers[j]}>\n`; } xml += `</row>\n`; } return xml; }
JavaScript
<row> <color>red</color> <maxSpeed>120</maxSpeed> <age>2</age> </row> <row> <color>blue</color> <maxSpeed>100</maxSpeed> <age>3</age> </row> <row> <color>green</color> <maxSpeed>130</maxSpeed> <age>2</age> </row>

This csvToXml() function is certainly not as versatile as the one from the csv-to-xml library, but as shown in the example above, it works for simple, straightforward CSV data.

You can modify it to allow for more complex and varying CSV data.

How to Add a Class to Multiple Elements in JavaScript

To add a class to multiple elements in JavaScript:

  1. Get a list of all the elements with a method like document.querySelectorAll().
  2. Iterate over the list with forEach().
  3. For each element, call classList.add(class) to add the class to each element.

i.e.:

JavaScript
const elements = document.querySelectorAll('.class'); elements.forEach((element) => { element.classList.add('class'); });

For example:

HTML
<p class="bold text">Coding</p> <p class="bold text">Beauty</p> <p class="bold text">Dev</p> <button id="add">Add class</button>
CSS
.bold { font-weight: bold; } .big { font-size: 1.2em; }
JavaScript
const elements = document.querySelectorAll('.text'); elements.forEach((element) => { element.classList.add('big'); });

This will be the HTML after the button is clicked.

HTML
<p class="big bold text">Coding</p> <p class="big bold text">Beauty</p> <p class="big bold text">Dev</p> <button id="add">Add class</button>
The big class to the paragraph elements when the button is clicked.
The big class to the p elements when the button is clicked.

We use the document.querySelectorAll() method to select all DOM elements to which we want to add the class.

We loop through the elements in the list object with its forEach() method. This forEach() method works much like Array forEach().

document.getElementsByClassName() method

We can use the document.getElementsByClassName() method in place of document.querySelectorAll() when the selector is a class selector. For getElementsByClassName(), we pass the class name without the . (dot), and we use Array.from() to convert the result to an array before the iteration with forEach().

JavaScript
const elements = Array.from(document.getElementsByClassName('text')); elements.forEach((element) => { element.classList.add('big'); });

Note: Unlike the querySelectorAll() method, getElementByClassName() returns a live list of HTML Elements; changes in the DOM will reflect in the array as the changes occur. If an element in the array no longer qualifies for the selector specified in getElementsByClassName(), it will be removed automatically. This means that one iteration of the list could be different from another, even without any direct modifications to the list.

classList.add() method

We use the classList.add() method to add a class to each of the elements.

You can add multiple classes by passing more arguments to add().

JavaScript
const elements = document.querySelectorAll('.text'); elements.forEach((element) => { element.classList.add('big', 'blue'); });

If any of the classes passed to add() already exists on the element, add() will ignore this, instead of throwing an error.

Add class to elements with different selectors

Sometimes there is no common selector between the elements that you want to add the class to. For such a case, you can pass multiple comma-separated selectors to the querySelectorAll() method.

JavaScript
const elements = document.querySelectorAll('.class-1, #id-1, tag-1'); elements.forEach((element) => { element.classList.add('class'); });

For example:

HTML
<p class="bold text">Coding</p> <p class="bold text">Beauty</p> <p class="bold text">Dev</p> <div id="box-1">English</div> <div>Spanish</div> <div id="box-2">French</div> <br /> <button id="add">Add class</button>
CSS
.bold { font-weight: bold; } .italic { font-style: italic; } .underline { text-decoration: underline; }
JavaScript
const elements = document.querySelectorAll('.text, #box-1, #box-2'); const addButton = document.getElementById('add'); addButton.addEventListener('click', () => { elements.forEach((element) => { element.classList.add('italic', 'underline'); }); });
Classes are added to elements with different selectors on button click.
Classes are added to elements with different selectors on button click.

Remove class from multiple elements

Just as the classList.add() adds one or more classes to an element, the classList.remove() removes one or more classes from an element.

So we can use it in a forEach() loop to a class to multiple DOM elements.

JavaScript
const elements = document.querySelectorAll('.text'); elements.forEach((element) => { element.classList.remove('big', 'bold'); });

How to Simulate a Mouse Click in JavaScript

In this article, we’ll learn multiple ways to easily simulate a mouse click or tap on an element in the HTML DOM, using JavaScript.

Use click() method

This is the easiest and most basic method to simulate a mouse click on an element. Every HTMLElement has a click() method that can be used to simulate clicks on it. It fires the click event on the element when it is called. The click event bubbles up to elements higher in the document tree and fires their click events.

JavaScript
const target = document.querySelector('#target'); target.click();

To use the click() method, you first need to select the element in JavaScript, using a method like querySelector() or getElementById(). You’ll be able to access the HTMLElement object from the method’s return value, and call the click() method on it to simulate the click.

Let’s see an example, where we simulate a button click every second, by calling click() in setInterval().

JavaScript
const target = document.querySelector('#target'); let clickCount = 0; const clickCountEl = document.getElementById('click-count'); clickCountEl.innerText = clickCount; // Programmatically click button every 1 second setInterval(() => { target.click(); clickCount++; clickCountEl.innerText = clickCount; }, 1000);
HTML
<button id="target">Target</button> <br /><br /> Clicks: <span id="click-count"></span>

Result

The button is clicked programmatically every 1 second.
The button is clicked programmatically every 1 second.

Notice how there are no visual indicators of a click occurring because it’s a programmatic click.

Since click() causes the click event to fire on the element, any click event listeners you attach to the element will be invoked from a click() call.

In the following example, we use a click event listener (instead of setInterval) to increase the click count, and another listener to toggle the button’s style when clicked.

JavaScript
const target = document.querySelector('#target'); let clickCount = 0; const clickCountEl = document.getElementById('click-count'); clickCountEl.innerText = clickCount; target.addEventListener('click', () => { clickCount++; clickCountEl.innerText = clickCount; }); target.addEventListener('click', () => { target.classList.toggle('btn-style'); }); setInterval(() => { target.click(); }, 1000);
HTML
<button id="target">Target</button> <br /><br /> Count: <span id="click-count"></span>
CSS
.btn-style { color: white; background-color: blue; border-radius: 2px; }
The click count is incremented and the button’s style is toggled from the simulated click.

Simulate mouse click with MouseEvent object

Alternatively, we can use a custom MouseEvent object to simulate a mouse click in JavaScript.

JavaScript
const targetButton = document.getElementById('target'); const clickEvent = new MouseEvent('click'); targetButton.dispatchEvent(clickEvent);

The MouseEvent interface represents events that occur from the user interacting with a pointing device like the mouse. It can represent common events like click, dblclick, mouseup, and mousedown.

After selecting the HTMLElement and creating a MouseEvent, we call the dispatchEvent() method on the element to fire the event on the element.

For example:

JavaScript
const clickEvent = new MouseEvent('click'); const targetButton = document.getElementById('target'); let clickCount = 0; const clickCountEl = document.getElementById('click-count'); clickCountEl.innerText = clickCount; targetButton.addEventListener('click', () => { clickCount++; clickCountEl.innerText = clickCount; }); setInterval(() => { const clickEvent = new MouseEvent('click'); targetButton.dispatchEvent(clickEvent); }, 1000);
HTML
<button id="target">Target</button> <br /><br /> Clicks: <span id="click-count"></span>
The button is clicked programmatically every 1 second.
The button is clicked programmatically every second with MouseEvent.

Any click event listener attached to the element is called with the MouseEvent object that was passed to dispatchEvent().

JavaScript
const clickEvent = new MouseEvent('click'); const targetButton = document.getElementById('target'); targetButton.addEventListener('click', (event) => { console.log(clickEvent === event); // true }); targetButton.addEventListener('click', (event) => { console.log(clickEvent === event); // true }); targetButton.dispatchEvent(clickEvent);

Result

The dispatched event object is passed to click listeners.
The dispatched MouseEvent is passed to click listeners.

Apart from the event type passed as the first argument, we can pass options to the MouseEvent() constructor to control specific details about the event:

JavaScript
const targetButton = document.getElementById('target'); const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: false, view: window }); targetButton.dispatchEvent(clickEvent);

The bubbles property determines whether the event can bubble up the DOM tree to the element’s containing elements.

The cancelable property determines whether or not the event’s default action can be prevented.

The view property sets the event’s AbstractView. You should pass the window object here.

Find more options in the MDN documentation for the MouseEvent() constructor and the now deprecated MouseEvent.initMouseEvent() method.

Simulate mouse click at position

We can also simulate a mouse click on an element at a specific position on the visible part of the webpage.

We do this by selecting the element with the document.elementFromPoint() method, and then simulating the click with the click() method.

JavaScript
const targetButton = document.elementFromPoint(x, y).click(); targetButton.click();

The elementFromPoint() method returns the topmost element at the specified coordinates, relative to the browser’s viewport. It returns an HTMLElement, which we call click() on to simulate the mouse click from JavaScript.

In the following example, we have a button and a containing div:

HTML
<div id="container"> <button id="target">Target</button> <br /><br /> Count: <span id="click-count"></span> </div>

Using CSS, we position the #container div to make its top-left corner exactly at the position (200, 100) in the viewport.

CSS
#container { position: absolute; top: 100px; left: 200px; height: 100px; width: 100px; border: 1px solid black; }

The #target button is at point (0, 0) in its #container, so point (200, 100) in the viewport.

To get the position of the #target with more certainty, we add an offset of 10px each to get the final position to search for: (210, 110).

JavaScript
let clickCount = 0; const clickCountEl = document.getElementById('click-count'); clickCountEl.innerText = clickCount; const targetButton = document.getElementById('target'); targetButton.addEventListener('click', () => { clickCount++; clickCountEl.innerText = clickCount; }); // Offset of 10px to get button's position in container const x = 200 + 10; const y = 100 + 10; setInterval(() => { const buttonAtPoint = document.elementFromPoint(x, y); buttonAtPoint.click(); }, 1000);

To verify that we’re actually selected the button by its position and it’s getting clicks, we select it by its ID (target) and set a click event listener on the HTMLElement returned, which will increase the count of how many times it has been clicked.

And we’re successful:

A click is simulated on the button at point (210, 110).

Simulate mouse click at position with MouseEvent object

We can also simulate a mouse click on an element at a certain (x, y) position using a MouseEvent object and the dispatchEvent() method.

Here’s how:

JavaScript
const clickEvent = new MouseEvent('click', { view: window, screenX: x, screenY: y, }); const elementAtPoint = document.elementFromPoint(x, y); elementAtPoint.dispatchEvent(clickEvent);

This time we specify the screenX and screenY options when creating the MouseEvent.

screenX sets the position where the click event should occur on the x-axis. It sets the value of the MouseEvent‘s screenX property.

screenY sets the position where the click event should occur on the Y-axis. It sets the value of the MouseEvent‘s screenY property.

So we can use MouseEvent to replace the click() method in our last example:

JavaScript
// ... // Offset of 10px to get button's position in container const x = 200 + 10; const y = 100 + 10; setInterval(() => { const buttonAtPoint = document.elementFromPoint(x, y); const clickEvent = new MouseEvent('click', { view: window, screenX: x, screenY: y, }); buttonAtPoint.dispatchEvent(clickEvent); }, 1000);

Note: screenX and screenY doesn’t decide where the click should occur (elementFromPoint does). These options are set so that they can be accessed from any click event listener attached to the element at the point.

How to Fix the “Unknown file extension .ts” Error in ts-node

The “Unknown file extension .ts” error occurs in ts-node occurs when "type": "module" is set in your package.json file. To fix it, run the TypeScript file with ts-node --esm my-file.ts, or remove "type": "module" from your package.json file.

For example, in a project with this package.json file:

package.json
{ "name": "cb-js", "version": "1.0.0", "main": "index.js", "type": "module", "license": "MIT", "devDependencies": { "prettier": "^2.8.1" } }

If you have a TypeScript file in your project, e.g., my-file.ts:

my-file.ts
const num: number = 10; console.log(num ** 2);

Running the ts-node index.ts command will result in the ERR_UNKNOWN_FILE_EXTENSION TypeError in ts-node:

The ERR_UNKNOWN_FILE_EXTENSION TypeError occurs.
The ERR_UNKNOWN_FILE_EXTENSION TypeError occurs.

To fix the “Unknown file extension ‘.ts'” error in ts-node, run ts-node with the --esm option set:

Shell
ts-node --esm my-file.ts # Or ts-node-esm my-file.ts # Or node --loader ts-node/esm my-file.ts
Running ts-node in esm mode.
Running ts-node in esm mode.

To avoid using the --esm flag, add the following to your tsconfig.json file:

tsconfig.json
{ // other settings... "ts-node": { "esm": true, "experimentalSpecifierResolution": "node" } }

After doing this, you’ll be able to run the TypeScript file with only ts-node:

Shell
ts-node my-file.ts
Running the TypeScript file with only ts-node.
Running the TypeScript file with only ts-node.

You may also need to add one or more of the following options to your tsconfig.json file:

tsconfig.json
{ // other settings.. "compilerOptions": { // other compiler options... "esModuleInterop": true, "module": "ESNext", // "module": "CommonJS" should work too "moduleResolution": "Node" }, "include": ["/**/*.ts"], "exclude": ["node_modules"] }

Remove "type": "module" from tsconfig.json file

Alternatively, instead of doing all of the above, you can simply remove the "type": "module" field from your package.json file to fix the ERR_UNKNOWN_FILE_EXTENSION error in ts-node.

tsconfig.json
{ "name": "cb-js", "version": "1.0.0", "main": "index.js", // removed: "type": "module", "license": "MIT", "devDependencies": { "prettier": "^2.8.1" } }

And you’ll be able to run the TypeScript file with ts-node successfully.

Compile TypeScript files into JavaScript

Another way to avoid ERR_UNKNOWN_FILE_EXTENSION is to stop using ts-node altogether. Instead, you can compile your TypeScript files with tsc and run the JavaScript output with node – the classic way.

Shell
# Compile with tsc npx tsc --outDir dist my-file.ts # Run with node node dist/my-file.ts

Basic TypeScript compilation setup

Here’s a great way to set up your project for easily compiling and debugging TypeScript files.

First, install the TypeScript compiler:

Shell
npm i tsc

Then specify the src dir and out dir in tsconfig.json, and enable source maps for seamless Typescript debugging:

tsconfig.json
{ "compilerOptions": { // ... other options "rootDir": "src", // Location of TypeScript files "outDir": "dist", // Location of compiled JavaScript files "sourceMap": true // Generate sourcemaps } }

Finally, create a start NPM script that automatically runs the tsc and node commands one after the other:

JavaScript
{ // ... other options "scripts": { "start": "tsc && node index.js" } }

Now you can run the script easily with npm start.

And you can debug TypeScript in VSCode too.

How to Get an Object Value By Key in TypeScript

You can easily get an object’s value by a key in Typescript using bracket notation, i.e., obj['key'], obj[myVar], etc. If the key exists, you will get the corresponding value back.

For example:

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car['name']); // CB Flash // Dot notation console.log(car.name); // CB Flash // Get value by variable key const prop = 'name'; console.log(car[prop]); // CB Flash // Computed property key const val = car[3 > 1 ? 'name' : 'maxSpeed'] console.log(val) // CB Flash

Dot notation property access

There are two ways to get an object’s value by a property key in TypeScript: dot notation and bracket notation.

In dot notation, we access an object value with the obj.propKey syntax.

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car.name); // CB Flash console.log(car.maxSpeed); // 200 console.log(car.color); // blue

With the obj.propKey syntax, the propKey must be a valid TypeScript identifier. Otherwise, a syntax error will be thrown:

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car.100 = 'go faster'; // ❌ SyntaxError console.log(car.100); // ❌ SyntaxError

propKey can also be a reserved keyword, like let, var, async, etc.

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car.let = 'works'; car.await = 'works too'; console.log(car.let); // works console.log(car.await); // works too

Bracket notation property access

In bracket notation, we access the property value with the obj[expression] syntax. The expression should evaluate to a string or Symbol that represent the property’s key.

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; console.log(car['name']); // CB Flash console.log(car['maxSpeed']); // 200 console.log(car['color']); // blue

Unlike dot notation, with bracket notation, we can access keys that are not valid TypeScript identifiers, like numbers and keys containing spaces.

TypeScript
type Car = { [propKey: string]: string }; const car: Car = {}; car['100'] = 'go faster'; car['year produced'] = 2022; console.log(car['100']); // go faster console.log(car['year produced']); // 2022

Computed property names

The expression we put in-between the brackets can be as complex as possible, as long it evaluates to a string or Symbol.

For example, we can put a ternary expression in-between the brackets:

TypeScript
type Car = { name: string; maxSpeed: number; color: string; }; const car: Car = { name: 'CB Flash', maxSpeed: 200, color: 'blue', }; const num = 3; const val = car[num > 1 ? 'name' : 'maxSpeed']; console.log(val); // CB Flash

Note: If the expression to the left of the ? is truthy, the ternary operator returns the value to the left. Otherwise, it returns the value to the right.

The ternary expression evaluates to the 'name' key, so the corresponding property value is returned.

You can also this computed property names approach to set a new property on a object.

TypeScript
type Car = { [propKey: string]: string | number; }; const car: Car = {}; const num = 7; car[num > 10 ? 'name' : 'maxSpeed'] = 500; console.log(car['name']); // undefined console.log(car['maxSpeed']); // 500

How to Get the Current Year in Vue.js

To get the current year in Vue.js, create a new Date object with the Date() constructor, then use the getFullYear() method to get the year of the Date. getFullYear() will return a number that represents the current year.

For example:

App.vue
<template> <div> {{ new Date().getFullYear() }} <div> &copy; {{ new Date().getFullYear() }} Coding Beauty </div> </div> </template>
The current year is displayed.
The current year is displayed.

We use the Date() constructor to create a new Date object. When Date() is called with no arguments, the Date object is created using the current date and time.

The Date getFullYear() method returns a number that represents the year of the Date. Since the Date object here stores the current date, getFullYear() returns the current year.

Get current year with data property

We can also put the current year in a data variable instead of placing it directly in the template with the {{ }} symbols. This allows us to more easily reuse the value in multiple places in the template markup.

App.vue
<template> <div> {{ currYear }} <div>&copy; {{ currYear }} Coding Beauty</div> </div> </template> <script> export default { data() { return { currYear: new Date().getFullYear(), }; }, }; </script>

Get current year with Composition API

Of course, this also works when using the Vue 3 Composition API:

App.vue
<script setup> const currYear = new Date().getFullYear(); </script> <template> <div> {{ currYear }} <div>&copy; {{ currYear }} Coding Beauty</div> </div> </template>

Get current month

If you also want to get the current month, the getMonth() method is for you.

getMonth() returns a zero-based index that represents the month of the Date. Zero-based here means that 0 = January, 1 = February, 2 = March, etc.

App.vue
<template> <div>Month number {{ currMonth }} in {{ currYear }}</div> </template> <script> export default { data() { return { currMonth: new Date().getMonth(), currYear: new Date().getFullYear(), }; }, }; </script>
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getmonth
The month number is displayed.

If you want the month name directly (the more likely case), the Date toLocaleString() method will do the job.

App.vue
<template> <div>{{ currMonth }} in {{ currYear }}</div> </template> <script> export default { data() { return { currMonth: new Date().toLocaleString([], { month: 'long', }), currYear: new Date().getFullYear(), }; }, }; </script>
The month name is displayed.

Check out this article for a full guide on how to convert a month number to its equivalent month name in JavaScript.

Get current day of month

Similarly, to get the current day in the month, you’d use the Date getDate() method:

App.vue
<template> <div>{{ currMonth }} {{ currDay }}, {{ currYear }}</div> </template> <script> export default { data() { return { currDay: new Date().getDate(), currMonth: new Date().toLocaleString([], { month: 'long', }), currYear: new Date().getFullYear(), }; }, }; </script>
The current day of the month is displayed.
The current day of the month is displayed.

Get current year, month, day, week…

While you could get each component of the date using different functions, a much more flexible and easy way to do this is by formatting the date in the given format with a format specifier.

We can carry out this formatting with the format() function from the date-fns library.

In the following example, we use date-fns format() to get the multiple individual parts of the date.

App.vue
<template> <div>{{ dateString }}</div> </template> <script> import { format } from 'date-fns'; export default { data() { return { dateString: format( new Date(), "EEEE, 'the' do 'of' LLLL, yyyy" ), }; }, computed() { return {}; }, }; </script>
Different parts of the date are displayed using formatting.
Different parts of the date are displayed using formatting.

The format() function takes a pattern and returns a formatted date string in the format specified by the pattern. You can find a list of the patterns format() accepts here.

For our example, we use the following patterns:

  • EEEE: to get the full name of the day of the week.
  • do: to get the ordinal day of the month, i.e., 1st, 2nd, 3rd, etc.
  • LLLL: to get the full name of the month of the year.
  • yyyy: to get the full year.

We also use single quotes to escape strings (the and of) that are not patterns but should be included in the result of the formatting.

When Exactly is the useEffect Hook Called in React?

The useEffect hook is called in a component after the first render and every time the component updates. By the timer useEffect is called, the real DOM would have been updated to reflect any state changes in the component.

Let’s take a look at a quick example to practically observe this behavior:

JavaScript
import { useEffect, useState } from 'react'; export default function App() { const [count, setCount] = useState(0); useEffect(() => { document.title = `Button Clicks: ${count}`; }, [count]) const handleAdd = () => { setCount((count) => count + 1); } return ( <div> Count: {count} <br /> <button onClick={handleAdd}>Add</button> </div> ); }

The first time the component renders from page loading, useEffect is called and uses the document.title property to set the page title to a string whose value depends on a count state variable.

The page title is changed from useEffect being called after the component renders.
The page title is changed from useEffect being called after the component is rendered.

If you watch closely, you’ll see that the page title was initially “Coding Beauty React Tutorial”, before the component was added to the DOM and the page title was changed from the useEffect call.

useEffect will also be called when the state is changed:

The page title is changed from useEffect being called after the component updated.
The page title is changed from useEffect being called after the component is updated.

As you might know, useEffect accepts an optional dependency array as its second argument. This array contains the state variables, props, and functions that it should watch for changes.

In our example, the dependency array contains only the count state variable, so useEffect will only be called when the count state changes.

useEffect called twice in React 18?

React 18 introduced a new development-only check to Strict Mode. This new check automatically unmounts and remounts a component when it mounts for the first time, and restores the previous state on the second mount.

Note: The check was added because of a new feature that will be added to React in the future. Learn more about it here.

This means that the first render causes useEffect to actually be called two times, instead of just once.

Here’s an example that lets us observe this new behavior.

JavaScript
import { useEffect, useState } from 'react'; export default function App() { const [time, setTime] = useState(0); useEffect(() => { setInterval(() => { setTime((prevTime) => prevTime + 1); }, 1000); }, []); return ( <div> Seconds: {time} </div> ); }

It’s a basic time-counting app that implements the core logic that can be used to build timer and stopwatch apps.

We create an interval listener with setInterval() that increments a time state by 1 every second. The listener is in a useEffect that has an empty dependency array ([]), because we want it to be registered only when the component mounts.

But watch what happens when we check out the result on the web page:

The seconds go up by 2 every second.
The seconds go up by 2 every second.

The seconds are going up by 2 every second instead of 1! Because React 18’s new check causes the component to be mounted twice, an useEffect is called accordingly.

We can fix this issue by unregistering the interval listener in the useEffect‘s cleanup function.

JavaScript
useEffect(() => { const timer = setInterval(() => { setTime((prevTime) => prevTime); }); // 👇 Unregister interval listener return () => { clearInterval(timer); } }, [])

The cleanup function that the useEffect callback returns is called when the component is mounted. So when React 18 does the compulsory first unmounting, the first interval listener is unregistered with clearInterval(). When the second interval listener is registered on the second mount, it will be the only active listener, ensuring that the time state is incremented by the correct value of 1 every second.

The second go up by 1 every second - success.
The seconds go up by 1 every second – success.

Note that even if we didn’t have this issue of useEffect being called twice, we would still have to unregister the listener in the cleanup function, to prevent memory leaks after the component is removed from the DOM.

How to Fix the “Unexpected reserved word (await)” Error in JavaScript

The “unexpected reserved word (await)” error occurs in JavaScript when you use the await keyword in a function that is not specified as async. To fix it, add an async modifier to the function to mark it as async.

The "Unexpected reserved word 'await'" error occurring in JavaScript.
The “Unexpected reserved word ‘await'” error occurring in JavaScript.

Here’s an example of the error occurring:

index.js
function getName() { // ❌ SyntaxError: Unexpected reserved word const str = await Promise.resolve('Coding Beauty'); return str; }

Note: As this is a syntax error, the function doesn’t need to be invoked for it to be detected, and no part of the code runs until it is resolved.

The async and await keywords work together in JavaScript (hence the commonly used term, async/await); to use the await keyword in a function, you must add the async modifier to the function to specify that it is an async function.

JavaScript
// ✅ Use "async" keyword modifier async function getName() { // ✅ Successful assignment - no error const str = await Promise.resolve('Coding Beauty'); return str; }

Fix “Unexpected reserved word (await)” error in nested function

If you’re using the await keyword, it’s likely that you already know that it has to be in an async function. What probably happened is that you nested functions and mistakenly ommited the async modifier from the innermost function containing the await keyword.

For example:

JavaScript
// ❌ SyntaxError: Unexpected reserved word export const createTask = async ({ description }) => // ❌ "async" keyword missing from innermost function (dispatch) => { await fetch('https://example.com/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ description }), }); dispatch({ type: 'taskCreated', description }); };

For await to work, the deepest function in the nesting hierarchy is required to be specified as async. It won’t work even if any or all of the outer functions are marked as async.

So we resolve the error in this case by adding the async modifier to the innermost function:

JavaScript
// ✅ No error export const createTask = async ({ description }) => // ✅ Innermost function marked as async async (dispatch) => { await fetch('https://example.com/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ description }), }); dispatch({ type: 'taskCreated', description }); };

In this example, we should be able to remove the async keyword from the outer function, as it isn’t performing any asynchronous operations with await, but this depends on whether the caller of createTask() is expecting it to return a Promise or not.

Here’s another example where this mistake frequently happens; using await in an array looping method:

JavaScript
// ❌ SyntaxError: Unexpected reserved word async function processPhotos(photoIds) { const data = await Promise.all(photoIds.map((photoId) => { const res = await fetch(`http://example.com/photos/${photoId}`); return await res.json(); })); // process data... }

Like in the previous example, the error occurs because the async keyword modifier is absent from the map() callback, even though it’s present in the function that calls map(). The fix is the same, add async to the map() callback.

JavaScript
// ✅ No error async function processPhotos(photoIds) { const data = await Promise.all( photoIds.map(async (photoId) => { const res = await fetch(`http://example.com/photos/${photoId}`); return await res.json(); }) ); // processing... }

Use await at top level

If you’re trying to use await at the top level of your file, you’ll need to set the type attribute to "module" in the script tag referencing the file in the HTML. This works when your code runs in browser environments.

For example:

index.html
<script type="module" src="index.js"></script>

Now you’ll be able to use await at the global scope in your file, e.g.:

index.js
console.log(await Promise.resolve('Coding Beauty'));

If you’re using Node.js, you’ll need to set the type attribute to "module" in your package.json file.

package.json
{ "name": "cb-js", "type": "module", "version": "1.0.0", "main": "index.js", "license": "MIT", // other fields... }

If there’s no package.json in your project directory, you can create one with the following command

Shell
# NPM npm init -y # Yarn yarn init -y

The await keyword will now work at the top level of your project files.