Borislav Hadzhiev
Mon Mar 14 2022·3 min read
Photo by Zachary Nelson
To solve the error "Cannot use import statement outside a module" in
TypeScript, set the module
option to commonjs
in your tsconfig.json
file
and make sure to compile your TypeScript files (e.g. with ts-node
), and not to
run them directly with node
.
First, make sure the module
option is set to commonjs
in your
tsconfig.json
file.
{ "compilerOptions": { "target": "es6", "module": "commonjs", "esModuleInterop": true, // ... your other options } }
The module option sets the module system for the program.
The esModuleInterop
option is set to false
by default, which causes it to treat CommonJS modules
similar to ES6 modules. This causes some issues. Setting esModuleInterop
to
true
fixes these issues.
Another common cause of the "Cannot use import statement outside a module" error
in TypeScript is trying to run a TypeScript file directly with node
, e.g.
node src/index.ts
. This doesn't work, because we first have to transpile the
file to JavaScript before we run it with node
.
The same is the case if you have incorrectly configured your TypeScript project
that uses babel
or ts-node
.
If your project uses ts-node
, you can try to add an override in your
tsconfig.json
, that sets module
to commonjs
.
{ "ts-node": { // these options are overrides used only by ts-node "compilerOptions": { "module": "commonjs" } }, "compilerOptions": { // ... your options }, }
main
property in your package.json
file points to your index.js
file, and not your index.ts
file.Take a look at your build folder, which you've set via the outDir
option in
your tsconfig.json
file. Your config could be wrong and you could still be
producing TypeScript files in your build directory.
If none of the suggestions above work, take a look at a working config for a
TypeScript project that uses ts-node
.
This is my tsconfig.json
file.
{ "compilerOptions": { "skipLibCheck": true, "target": "es6", "module": "commonjs", "moduleResolution": "node", "allowJs": true, "resolveJsonModule": true, "esModuleInterop": true, "outDir": "./build", "rootDir": "src", }, "include": ["src/**/*"], "exclude": ["node_modules"] }
Make sure the include
array points to a directory that contains all of the
necessary files for your project.
This is my package.json
file.
{ "name": "example", "version": "1.0.0", "main": "build/index.js", "scripts": { "build": "rimraf ./build && tsc", "dev": "nodemon", "start": "npm run build && node build/index.js", }, "devDependencies": { "@types/node": "^17.0.21", "nodemon": "^2.0.15", "rimraf": "^3.0.0", "ts-node": "^10.4.0", "typescript": "^4.6.2" } }
And here is the nodemon.json
configuration file, which is located in the same
directory.
{ "watch": ["src"], "ext": ".ts,.js", "ignore": [], "exec": "ts-node --files ./src/index.ts" }
src
and have an index.ts
entry point under src/index.ts
.The ts-node
package will transpile your code to JavaScript and run it with
node
.
Your build files will be in the build
directory. Note that your build
directory should not contain any TypeScript files, it should only contain
JavaScript files.
If your build directory contains TypeScript files, you have a configuration error in your project.