I have spent an hour now searching for a solution to a new error after needing top-level await. Everything else I have tried so far did not solve the error such as adding "type": "module"
to the package.json file.
The message of the error is Cannot use import statement outside a module
when starting the service. If I revert the change "module": "ESNext",
to "module": "commonjs",
, it works fine (except the await keywords have to be removed and somehow refactored to work without await).
In addition, I use ts-node-dev to run the service which can be seen in the package.json file.
package.json
{ "name": "", "version": "1.0.0", "description": "microservice", "main": "src/index.ts", "author": "", "type": "module", "license": "MIT", "scripts": { "dev": "NODE_ENV=development tsnd --respawn --files src/index.ts", "prod": "NODE_ENV=production tsnd --respawn --transpile-only --files src/index.ts", "test": "mocha --exit -r ts-node/register tests/**/*.spec.ts", "eslint": "eslint src/**/*.ts" },
tsconfig.json
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "node", "outDir": "dist", "sourceMap": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true }, "ts-node": { "files": true, "transpileOnly": true }, "include": ["src/**/*.ts", "declariations/**.d.ts"], "exclude": ["node_modules", ".vscode"] }
ts-node is a TypeScript execution engine and REPL for Node. js. It JIT transforms TypeScript into JavaScript, enabling you to directly execute TypeScript on Node. js without precompiling.
ts-node supports a variety of options which can be specified via tsconfig.
We can use the ts-node package to execute TypeScript files from the command line. Install it with npm or other package manager. After that, simply execute the TypeScript files with the command: ts-node filename.
As of v1. 19.0, nodemon has inbuilt support for TypeScript files with help from ts-node that requires no manual configuration. By default, nodemon uses the node CLI as an execution program for running JavaScript files; for TypeScript files, nodemon uses ts-node as the execution program instead.
TL;DR: Don't use ECMAScript modules with ts-node or ts-node-dev (yet); just refactor the top-level await out
Today I tumbled down the same rabbit hole, starting with the innocuous error:
Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
As a result, I felt inclined to edit my tsconfig.json
and set module
to esnext
, which in turn forced me to set moduleResolution
to node
and finally add type: module
to my package.json
. What I failed to realize (and IMO they shouldn't suggest this in the error message-- you can just simply refactor the top-level await out), that this switches the module resolution strategy of NodeJS from CommonJS to ESM. This is actually a big deal for many reasons:
I feel that at this time (december 2020) the NodeJS ecosystem is still in transition from the classic CommonJS modules to the new ECMAScript modules. As a result other tech like ts-node or ts-node-dev are transitioning as well and support can be flaky. My advice is to stick with CommonJS until the dust has settled and these things "just work" out of the box.
I know, the question is quite old already, but for people passing by this issue like I did earlier today:
I just managed to get it to work. Not with ts-node-dev
directly, but with the combination of nodemon
and ts-node
.
You need to install nodemon
and ts-node
and then, assuming your entry file is src/index.ts
, you can use this command:
nodemon --ext ts --loader ts-node/esm --experimental-specifier-resolution node src
(Tested with Node v16.13.0)
This was the key post for me to figure it out: https://github.com/TypeStrong/ts-node/issues/1007
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With