ts-node: SyntaxError: Cannot use import statement outside a module

I use nextjs

import koa from 'koa'
import next from 'next'
import clear from 'clear'
import body from 'koa-bodyparser'
import cors from 'koa-cors'
import logger from 'koa-logger'
import Api from './router'
const dev = process.env.NODE_ENV !== 'production'
const App = next({ dev })
const handle = App.getRequestHandler()
const PORT = parseInt(process.env.NODE_PORT) || 3000

App.prepare().then(() => {
  const Server = new koa()

  Server.use(body())
  Server.use(cors())
  Server.use(logger())

  Server
    .use(Api.routes())
    .use(Api.allowedMethods())

  Server.use(async ctx=> {
    // https://thecodebarbarian.com/building-a-nextjs-app-with-mongodb
    await handle(ctx.req, ctx.res)
    ctx.respond = false
  })

  Server.listen(PORT, () => {
    clear()
    const cowsay = require('cowsay-browser')
    const text = `Koa server listen in ${ PORT }`
    console.log(cowsay.say({ text }))
  })

})

use ts-node server.ts, BTW

➜  next git:(dev) ✗ ts-node server.ts 
/home/d1y/cat/coface/code/next/server.ts:10
import koa from 'koa';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Module._compile (internal/modules/cjs/loader.js:892:18)
    at Module.m._compile (/usr/node/node-v12.13.0-linux-x64/lib/node_modules/ts-node/src/index.ts:536:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Object.require.extensions.<computed> [as .ts] (/usr/node/node-v12.13.0-linux-x64/lib/node_modules/ts-node/src/index.ts:539:12)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at main (/usr/node/node-v12.13.0-linux-x64/lib/node_modules/ts-node/src/bin.ts:212:14)
    at Object.<anonymous> (/usr/node/node-v12.13.0-linux-x64/lib/node_modules/ts-node/src/bin.ts:470:3)
    at Module._compile (internal/modules/cjs/loader.js:956:30)

my tsconfig.json file

{
  "compilerOptions": {
    "target": "es6",
    "lib": [
      "es6"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "es2015",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "noImplicitAny": true
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ]
}

Why is this?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 129
  • Comments: 44 (2 by maintainers)

Commits related to this issue

Most upvoted comments

@Dravere we also support overriding compilerOptions inside the same tsconfig, which will only apply to ts-node. So you can keep it all in a single tsconfig file if you want.

{
  "ts-node": {
    // these options are overrides used only by ts-node
    // same as our --compilerOptions flag and our TS_NODE_COMPILER_OPTIONS environment variable
    "compilerOptions": {
      "module": "commonjs"
    }
  },
  "compilerOptions": {
    "module": "esnext"
  }

When using a tsconfig.json, you may override just the module setting like this:

$ npx ts-node -O '{"module":"commonjs"}' my-script.ts

I had the same problem and somehow fixed it. I have written a post about this, hope this helps https://xperimentalhamid.com/how-do-i/fix-cannot-use-import-statement-outside-a-module/

Update 3: Since Node 13, you can use either the .mjs extension or set “type”: “module” in your package.json. You don’t need to use the --experimental-modules flag.

Update 2: Since Node 12, you can use either the .mjs extension or set “type”: “module” in your package.json. And you need to run node with the --experimental-modules flag.

Update: In Node 9, it is enabled behind a flag, and uses the .mjs extension.

node --experimental-modules my-app.mjs

https://stackoverflow.com/questions/39436322/node-js-syntaxerror-unexpected-token-import?rq=1

You’re trying to execute use it as an ES2015 module, but node.js currently understands CommonJS.

Having the same problem even when using commonjs

	"compilerOptions": {
		/* Basic Options */
		"target": "es2016",
		/* Specify ECMAScript target version: 'ES3' (default),	'ES5',	'ES2015',	'ES2016',	'ES2017',	'ES2018' or 'ESNEXT'. */
		"module": "commonjs",

My project is an expo react-native project, but that shouldn’t make a difference.

But the error does seem to come from a dependency:

.../node_modules/expo-constants/build/Constants.js:1
import { AppOwnership, UserInterfaceIdiom, } from './Constants.types';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Module._compile (internal/modules/cjs/loader.js:895:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)

“type”: “module” works, but only works if you are using Node v13.9.0 or above.

Add .babelrc to root folder

  • ~/.babelrc
{
  "presets": ["env", "stage-0"]
}

my package.json

  • ~/package.json
"scripts": {
    "watch": "nodemon --exec babel-node src/index.js"
  },
  "dependencies": {
    "dotenv": "^8.2.0",
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-stage-0": "^6.24.1",
    "nodemon": "^2.0.3"
  }

@Dravere we also support overriding compilerOptions inside the same tsconfig, which will only apply to ts-node. So you can keep it all in a single tsconfig file if you want.

{
  "ts-node": {
    // these options are overrides used only by ts-node
    // same as our --compilerOptions flag and our TS_NODE_COMPILER_OPTIONS environment variable
    "compilerOptions": {
      "module": "commonjs"
    }
  },
  "compilerOptions": {
    "module": "esnext"
  }

this works! thanks a lot!

For those of you simply trying to run a typescript file using ts-node from the command line I got it to work by:

Solution Changing my tsconfig.json to have this:

"module": "commonjs",

instead of this:

"module": "esnext",

fixed it.

Why If you want to understand why this fixes it, here’s a really good article on what module means and the difference between esnext and commonjs: https://www.tsmean.com/articles/learn-typescript/typescript-module-compiler-option/

Key point: So all in all this can be summarized as: Using TypeScript, node.js and the TypeScript compiler option “module”: “esnext” together is next to impossible. So if you’re building code that should be ran with node.js, in 2020, you should still choose “module”: “commonjs”.

This is pretty hilarious:

😸 hey bro, we got this tool that lets you run typescript on the cli!!!

🧑‍💻 Amazeballs! proceeds to type standard typescript with imports in a .ts file

💻 Error you are fail, re-evaluate life choices

🧑‍💻 🕸️ OMG QQ WTFBBQ, what is this error: ....

lib author: ./wontfix

Other Rando on the internet commenting on a typescript tool: hey lol use .mjs 👍🏻 👍🏻 👍🏻 👍🏻

🧑‍💻 ._. dude, this is typescript.

Yet Another Rando on the internet commenting on a typescript tool: hey lol add a .babelrc lmao 👍🏻 👍🏻 👍🏻 👍🏻

🧑‍💻 ./leavesbuilding

Thanks, I got it fixed that way!

For me setting esModuleInterop to true was the fix.

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

I had the same problem and somehow fixed it. I have written a post about this, hope this helps https://xperimentalhamid.com/how-do-i/fix-cannot-use-import-statement-outside-a-module/

.mjs extension worked for me, thank you!!

Now that we’ve got top level await as an unflagged feature for Node 14, and TS requires using module: "esnext" to utilize that, this bones anyone trying to use ts-node with that feature.

I’m a beginner in NodeJS, and well After adding "type": "module" I still have this issue, my node version is v14.3.0 and all solutions above didn’t work. and I can’t keep using require() because it’s not so flexible.

Apparently, nothing happened after adding that: still doesnt work - import - module

I had the same problem when I started to used babel… But later, I had a solution… I haven’t had the problem anymore so far… Currently, Node v12.14.1, “@babel/node”: “^7.8.4”, I use babel-node and nodemon to execute (node is fine as well…)

package.json: “start”: "nodemon --exec babel-node server.js “debug”: “babel-node debug server.js” !!note: server.js is my entry file, you can use yours.

launch.json: When you debug, you also need to config your launch.json file “runtimeExecutable”: “${workspaceRoot}/node_modules/.bin/babel-node”

Of course, with babel-node, you also normally need and edit another file, such as babel.config.js/.babelrc file

Update 3: Since Node 13, you can use either the .mjs extension or set “type”: “module” in your package.json. You don’t need to use the --experimental-modules flag.

Update 2: Since Node 12, you can use either the .mjs extension or set “type”: “module” in your package.json. And you need to run node with the --experimental-modules flag.

Update: In Node 9, it is enabled behind a flag, and uses the .mjs extension.

node --experimental-modules my-app.mjs

https://stackoverflow.com/questions/39436322/node-js-syntaxerror-unexpected-token-import?rq=1

How am I supposed to use mjs extension for the ts file? There is typescript-specific code present (like setting type) which is not possible in mjs or in any other file type.

For eg. I got these two errors SyntaxError: Unexpected token ':' and Type annotations can only be used in TypeScript files.ts(8010) in this code, when I changed extension form ts to mjs

function run(): void {   // <------- Colon (:) is causing SyntaxError: Unexpected token ':' and
                         //          void is causing error Type annotations can only be used in TypeScript files.ts(8010)
      // Some code
}

@Nditah

@danielcnascimento npm run typeorm:migration:run

image

If its an express project make this the last line in your server.js or app.js file module.exports = app; where app is from declared earlier, this this can be any valid variable but here app is used. const app = express();

@cspotcode Oh, that is amazing. Thanks for that hint. Learned a lot about Typescript and ts-node while trying to fix that problem.

In case you stumble upon this and don’t want to change the module option to commonjs because this will mess with your tree shaking in webpack. You can have more than one tsconfig.json. ts-loader supports a config entry named configFile. There is also a possibility for extending tsconfig.json files.

In my case I had a vue project and I wanted to test some parts of it with mocha/chai. I created a tsconfig.base.json with the common options. The tsconfig.json file extends the base file and is setup to run with mocha. It’s module setting is set to commonjs. Additionally I created a tsconfig.webpack.json extending the base file that has its module config set to es2015 that is provided to configFile in the ts-loader options. I changed no other options anywhere else, so no type: "module" in package.json that was mentioned in this issue since this would interfere with webpack 4.x.

Also as additional info ts-node supports providing a different tsconfig.json via the -P or --project command line option.

@netpoetica also please move this to our discussion forum since it looks like it’s not a bug report or a feature request. Answers given in the discussion forum are more discoverable, meaning it is more likely that the next person with this issue will benefit from the answer as well. This saves work on the whole.

i keep getting this error when i import react in node for some reason in my project `` import React from ‘react’ ^^^^^^

SyntaxError: Cannot use import statement outside a module ``