I want to use imports (import x from y
) and top-level awaits at the same time with ts-node. However if I change my tsconfig.compilerOptions.module
to es2017
or higher as required by top-level awaits I get:
SyntaxError: Cannot use import statement outside a module
The fix for this is according to countless GH issues and SO questions to set tsconfig.compilerOptions.module
to commonjs
which in turn results in:
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 I have both? There has to be a way...
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"]
}
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.
I believe this was primarily an issue for you because you used "moduleResolution: "node"
in your tsconfig.json
. Nowadays you're much better off setting "module": "nodenext"
and "moduleResolution: "nodenext"
.
This answer has nothing to do with ts-node
but only involves Node.js and TypeScript. You're better off using tsx
which requires no configuration instead of ts-node
.
Given the following project:
.
├── 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)
Now run ./node_modules/.bin/tsc
to generate the build in dist/
.
Now run node dist/main.js
:
something async
y
The following versions of Node.js and TypeScript were used:
If you need to use ts-node
I can dig in further, but you didn't really explain why you needed that tool. Also, I would consider tsx
over ts-node
if you want to execute .ts
files directly for whatever reason.
Using tsx@4.9.3
you can get the same output by running:
./node_modules/.bin/tsx src/main.ts