Combining normal imports with top-level await: A guide

Is it possible to simultaneously use imports (import x from y) and top-level awaits with ts-node? I encountered an issue where changing my tsconfig.compilerOptions.module to es2017 or higher, as required by top-level awaits, resulted in the following error:

SyntaxError: Cannot use import statement outside a module

The solution suggested by numerous GitHub issues and Stack Overflow questions is to set tsconfig.compilerOptions.module to commonjs. However, this then leads to another issue:

Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher

How can both conditions be met simultaneously? There must be a way...

Here's my tsconfig.json:

{
  "compilerOptions": {
    "declaration": true,
    "module": "esnext",
    "target": "es2017",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "outDir": "dist",
    "skipLibCheck": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"]
}

And my package.json:

{
  "name": "x",
  "version": "0.0.1",
  "main": "main.js",
  "type": "module",
  ...
}

I am using Node LTS (v16.14.2) and TypeScript 4.6.3.

Answer №1

It seems that the main issue you encountered was related to the configuration in your tsconfig.json. Instead of using

"moduleResolution: "node"
, it is recommended to switch to
"module": "nodenext"
and
"moduleResolution: "nodenext"
.

This solution focuses on Node.js and TypeScript setup, rather than involving ts-node. You may find it more beneficial to opt for tsx as an alternative without any additional configuration requirements. Refer to this link for further details.

The sample project structure is:

.
├── src/
│   ├── y.ts
│   └── main.ts
├── package.json
└── tsconfig.json

package.json

"type": "module"

tsconfig.json

{
  "compilerOptions": {
     "target": "ESNext",
     "module": "NodeNext",
     "moduleResolution": "Nodenext",
     "outDir": "dist"
  },
  "include": ["src"]
}

src/y.ts

const doSomethingAsync = () => Promise.resolve('something async')

export { doSomethingAsync }
export default 'y'

src/main.ts

import { doSomethingAsync } from './y.js'
import x from './y.js'

console.log(await doSomethingAsync())
console.log(x)

To compile the code, run ./node_modules/.bin/tsc to generate the build files in dist/.

Execute the compiled code by running node dist/main.js:

something async
y

The versions used for Node.js and TypeScript were:

  • Node.js 22.1.0
  • TypeScript 5.4.5

If you still require the use of ts-node, please provide more context. For direct execution of .ts files, consider using tsx instead of ts-node.

For the equivalent output with tsx, utilize the command:

./node_modules/.bin/tsx src/main.ts

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue TS1112: It is not possible to declare a class member as optional

I'm currently working on creating a movie catalog using Angular and Ionic. Within the Movie class, I have properties for id, title, image, and plot. On the initial page of the app, only the id, title, and image are displayed, while the plot is omitte ...

Sending data to the makeStyle function in TypeScript

How can I set the style of backgroundImage in my React component based on the value of post.mainImage? Here is the code snippet: import React from 'react'; import { Post } from '../interfaces'; import { makeStyles, createStyles, Theme ...

Instance of exported class declared in Typescript

Currently, I am in the process of developing my initial declaration file for a foreign library known as react-native-background-timer. Within this library, there exists a default export that I am uncertain about how to declare within the index.d.ts file. ...

Sharing a FormGroup between different components

For my Angular 2+ application utilizing reactive forms, I have a requirement to share the main FormGroup across multiple components. This will allow different sections of the form such as header and footer to be managed independently by separate components ...

What causes @typescript-eslint to retain old types/files in its cache and prevent successful compilation?

When I kick off my Typescript application using tsc -b -w, I always encounter an issue with @typescript-eslint not reacting to file changes accurately. It flags invalid types/syntax errors where there are none. Restarting the process sometimes doesn't ...

Display Bootstrap Modal using Typescript in Angular

Looking for some creative ideas here... My Angular site allows users to register for events by filling out a form. They can also register themselves and other people at the same time. https://i.sstatic.net/a44I7.png The current issue ~ when a user clicks ...

Navigating through multiple pages using an Observable in Angular

After countless attempts, I still haven't been able to figure it out. Any assistance would be greatly appreciated; I recently came across Angular and RxJs. The issue I'm facing involves a service that fetches resources from various URLs of the s ...

What is the best way to compare an array with comma-separated values in JavaScript?

I have a scenario where I have two arrays, one for categories and the other for products. Each product contains multiple categories as a comma-separated string. My goal is to match a specific category with each product's product_category value and the ...

Oops! Property 'month' cannot be set on undefined value due to a TypeError

Despite not receiving any errors from Visual Studio Code, I’m encountering an error in Chrome's console. Below is the code snippet from my interfaces.ts file: export interface Data1{ month: string; employeeName: string; date: string; employmentSta ...

Relaying numerous references in TypeScript

Having some trouble forwarding an object of refs in TypeScript and struggling with how to properly type them. Here are the refs and the way I'm passing them into my component. const storyRef = useRef<HTMLElement>(null); const parcoursRef = useR ...

Establish a connection to Cosmos DB from local code by utilizing the DefaultAzureCredential method

I've created a Typescript script to retrieve items from a Cosmos DB container, utilizing the DefaultAzureCredential for authentication. However, I'm encountering a 403 error indicating insufficient permissions, which is puzzling since I am the ad ...

Is there a way to sort the output of an observable in various different methods?

One interesting feature I have implemented is a TableData type observable that provides me with a collection of table rows and columns. The user has the option to select a set of columns from a dropdown menu (which corresponds to the rows) to be sorted in ...

The type 'HTMLDivElement | null' cannot be assigned to the type 'HTMLDivElement' in this context

Struggling with a scroll function to maintain position while scrolling up or down - encountering an error: Error: Type 'HTMLDivElement | null' is not assignable to type 'HTMLDivElement'. Type 'null' is not assignable to type & ...

Determining the total number of items in an array in Angular efficiently without causing any lag

Currently, I am using the function checkDevice(obj) to validate if a value is present or not. In addition to this functionality, I also require a separate method to determine the number of occurrences of Device in the Array. component.ts public checkDevi ...

What could be causing my controller method in TypeScript to throw an error message unexpectedly?

Hey there. I'm diving into TypeScript and currently working on converting an Express backend to TS. Everything was smooth sailing until I encountered some unexpected issues. Specifically, the lines const hasVoted = poll.votedBy.some((voter): boolean = ...

Utilizing the useRef hook in React to retrieve elements for seamless page transitions with react-scroll

I've been working on creating a single-page website with a customized navbar using React instead of native JavaScript, similar to the example I found in this reference. My current setup includes a NavBar.tsx and App.tsx. The NavBar.tsx file consists o ...

Zero-length in Nightmare.js screenshot buffer: an eerie sight

I'm currently working on a nightmare.js script that aims to capture screenshots of multiple elements on a given web page. The initial element is successfully captured, but any subsequent elements below the visible viewport are being captured with a l ...

Issue encountered when utilizing TypeORM within NestJS: Unable to import Entity Repository

Issue with EntityRepository Import Despite having @nestjs/typeorm installed, VS Code is not recognizing the decorator I need to use. Any suggestions on how to resolve this? ...

What is the syntax for using typeof with anonymous types in TypeScript?

After reading an article, I'm still trying to grasp the concept of using typeof in TypeScript for real-world applications. I understand it's related to anonymous types, but could someone provide a practical example of how it can be used? Appreci ...

What is the best way to utilize v-model with an array of strings in a Vuex store when using v-for

Encountered an issue while trying to set a value in an Array within the Vuex Store: VueCompilerError: v-model cannot be used on v-for or v-slot scope variables because they are not writable. Seeking alternatives to achieve this without creating a local co ...