简体   繁体   English

Typescript:无法在模块外使用导入语句

[英]Typescript: Cannot use import statement outside a module

I have a.ts file in node.js (latest version of node.js for 07.10.19) app with importing node-module without default export.我在 node.js(07.10.19 的最新版本 node.js)应用程序中有一个 .ts 文件,其中导入了没有默认导出的节点模块。 I use this construction: import { Class } from 'abc';我使用这个结构: import { Class } from 'abc'; When i run the code, i have this error: Cannot use import statement outside a module .当我运行代码时,我有这个错误: Cannot use import statement outside a module

In the.network i see many solutions for this problem (for.js), but it not helps to me, maybe because i have typescript file.在 .network 中,我看到了这个问题的许多解决方案 (for.js),但对我没有帮助,可能是因为我有 typescript 文件。 Here's my code:这是我的代码:

import { Class } from 'abc';
module.exports = { ...
    execute(a : Class ,args : Array<string>){ ...

Here's my tsconfig.json:这是我的 tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",

    "strict": true
  }
}

Update: Because this answer is getting significant views I have updated it to better show the available solutions for this problem in 2022.更新:因为这个答案获得了重要的意见,我已经更新了它,以更好地展示 2022 年这个问题的可用解决方案。


The error means Node found an import statement in a file that it does not consider an ECMAScript (ES) module.该错误意味着 Node 在文件中发现了一个它不认为是 ECMAScript (ES) 模块的import语句。 Adding "type": "module" to package.json will tell Node you are using ES modules, but then you will need to tell the TypeScript compiler to emit this type of module by setting "module": "es2015" or higher (for example: "es2020" ) in tsconfig.json .添加 "type": "module": "es2015" "type": "module"package.json会告诉 Node 你正在使用 ES 模块,但是你需要告诉 TypeScript 的 TypeScript 编译器发出这个例如: "es2020" )在tsconfig.json中。 If you want to emit CommonJS modules ( require ), set "module": "commonjs" .如果你想发出 CommonJS 模块( require ),设置"module": "commonjs"

In case you don't want to set the module system at the project level, there are more fine-grained options.如果您不想在项目级别设置模块系统,还有更细粒度的选项。 Files with the .mjs extension are always treated as ES modules, while files with .cjs are always treated as CommonJS modules.带有.mjs扩展名的文件始终被视为 ES 模块,而带有.cjs的文件始终被视为 CommonJS 模块。 As of TypeScript 4.5 it is possible to use the .mts and .cts extensions as well and have the compiler emit .mjs or .cjs files, respectively.从 TypeScript 4.5 开始,也可以使用.mts.cts扩展名,并让编译器分别发出.mjs.cjs文件。

The two systems are partially compatible.这两个系统是部分兼容的。 For example, it is possible to import a CommonJS module into an ES module with a default export:例如,可以使用默认导出将 CommonJS 模块导入 ES 模块:

// in an ES module
import thing from "./main.cjs";

The other way around.另一种方式。 an ES module may be imported into a CommonJS module with dynamic import (ES2020 features are needed for this to work):一个 ES 模块可以通过动态导入导入到 CommonJS 模块中(需要 ES2020 特性才能工作):

// in a CommonJS module
const thing = await import("./main.mjs");

Original answer (2020):原始答案(2020):

Adding "type": "module" to package.json will tell Node you are using ES2015 modules, which should get rid of the error, but then you will need to tell Typescript to generate this type of module by setting "module": "es2015" instead of "commonjs" in tsconfig.json ."type": "module"添加到package.json将告诉 Node 您正在使用 ES2015 模块,这应该可以消除错误,但是您需要通过设置告诉 Z9327DAFFB330417F87934CC99F 模块的生成类型为"module": "es2015"而不是 tsconfig.json 中的"commonjs" tsconfig.json

This however causes a problem with the current code because although you are using an ES6 import {} statement you are exporting using the commonJS module.exports = {} syntax, and Node's ES module loader will have an issue with it.然而,这会导致当前代码出现问题,因为尽管您使用的是 ES6 import {}语句,但您正在使用 commonJS module.exports = {}语法导出,并且 Node 的 ES 模块加载器会出现问题。 There are two ways to deal with it:有两种方法可以处理它:

  • Keep the module.exports but tell Node to interpret this file as commonJS by giving it a.cjs extension.保留 module.exports 但告诉 Node 将此文件解释为 commonJS 通过给它一个.cjs 扩展名。
  • Change the export statement to ES2015 syntax: export function execute(…)..将导出语句更改为 ES2015 语法: export function execute(…)..

The first option could get a bit tricky because the compiler will output.js files and you'd have to change it to.cjs all the time (as far as I know).第一个选项可能会有点棘手,因为编译器将 output.js 文件,并且您必须一直将其更改为.cjs(据我所知)。 With the second option you should be able to run the file with Node (including the --experimental-modules flag for versions < 13.8).使用第二个选项,您应该能够使用 Node 运行文件(包括版本 < 13.8 的 --experimental-modules 标志)。

If you absolutely need to use commonJS, perhaps it is better to install the type definitions for Node: @types/node and change the import to commonJS format: require('abc') and keep the rest of the settings as they are (though you can add "type": "commonjs" to package.json to be explicit).如果您绝对需要使用 commonJS,也许最好安装 Node 的类型定义: @types/node并将导入更改为 commonJS 格式: require('abc')并保持设置的 rest 原样(尽管您可以将"type": "commonjs"添加到 package.json 以明确)。

Make sure your "main" field in package.json is pointing to the compiled index.js and not the index.ts确保package.json中的"main"字段指向已编译的index.js而不是index.ts

If you happen to be using ts-node , you can set some compiler options in tsconfig.json specifically for ts-node to use.如果您碰巧使用ts-node ,您可以在tsconfig.json中设置一些编译器选项,专门供ts-node使用。

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

Then you can just execute your script pretty easily:然后你可以很容易地执行你的脚本:

$ ts-node my-script.ts

I had very similar issue.我有非常相似的问题。 I had to install nodemon and always start script through nodemon index.ts我必须安装nodemon并始终通过nodemon index.ts启动脚本

yarn add -D nodemon

package.json package.json

"scripts": {
   "start": "nodemon index.ts"
}

or to specify the file from the command line或从命令行指定文件

package.json package.json

"scripts": {
   "nodemon": "nodemon $1"
}

There can be a lot of of possibilities for getting,获得的可能性有很多,

SyntaxError: Cannot use import statement outside a module SyntaxError: 不能在模块外使用 import 语句

while running typescript.在运行 typescript 时。

In my setup, I was importing a module called, AbModule ( AbModule has class AbClassName ) from my script testab.ts .在我的设置中,我从脚本testab.ts导入了一个名为AbModule的模块( AbModule有 class AbClassName )。

testab.ts had import stmt , testab.tsimport stmt

import {AbClassName} = 'testAdapterDir/AbModule.po.ts';

However, AbModule had all *.ts files and there were *.js files were not present.但是, AbModule具有所有*.ts文件,并且不存在*.js文件。 fix is,修复是,

You may get errors in running the below code but you can safely ignore them.您可能会在运行以下代码时遇到错误,但您可以放心地忽略它们。

cd AbModule path
tsc *.ts

Now AbModule should contain compiled files all *.js too.现在AbModule也应该包含所有*.js的编译文件。 Now run testab.ts and noticed that the mentioned error does not exist anymore,现在运行testab.ts并注意到提到的错误不再存在,

In tsconfig.json set:tsconfig.json设置:

  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }

Solution if "type": "module" is NOT an option解决方案如果"type": "module"不是一个选项

  • rename .ts to .mts.ts重命名为.mts
  • run ts-node --esm file.mts运行ts-node --esm file.mts

here's my tsconfig.json for reference:这是我的tsconfig.json供参考:

{
  "compilerOptions": {
    "incremental": true,
    "target": "ESNext",
    "module": "ESNext",
    "allowJs": true,
    "checkJs": false,
    "outDir": "./dist",
    "sourceMap": true,
    "strict": true,
    "alwaysStrict": true,
    "moduleResolution": "node",
    "esModuleInterop": true
  },
  "include": ["**/*"]
}

I had similar issue with one Node TypeScript project.我在一个 Node TypeScript 项目中遇到了类似的问题。 I needed some features of ESM, and when changed "target" and "module" in tsconfig.json to ESNext , I've got an error "Cannot use import statement outside a module".我需要 ESM 的一些功能,当将ESNext中的"target""module"更改为tsconfig.json时,出现错误“无法在模块外使用导入语句”。

The solution helped me was:对我有帮助的解决方案是:

  1. implement "type": "module" in package.jsonpackage.json中实现"type": "module"
  2. implement "target": "ESNext" and "module": "NodeNext" in tsconfig.json (afterwards I checked that "module": "ESNext" worked as well by the way)在 tsconfig.json 中实现"target": "ESNext""module": "NodeNext" tsconfig.json后来我检查了"module": "ESNext"顺便说一下也能正常工作)
  3. change all import statement in *.ts files adding js extension like this import { AccountGroup } from "./AccountGroup.js" (despite that actual code in TypeScript project before compilation is inside AccountGroup.ts file)更改*.ts文件中的所有导入语句,添加这样的js扩展名import { AccountGroup } from "./AccountGroup.js" (尽管编译前 TypeScript 项目中的实际代码在AccountGroup.ts文件中)

Solution was found here and was inspired by this source解决方案是在这里找到的,并受到这个来源的启发

install package ts-node and change your package.json安装 package ts-node 并更改您的 package.json

"scripts": {
    "dev": "ts-node index.ts"
  }

UPD: This can occur while using ts-node UPD:这可能在使用 ts-node 时发生

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeScript:无法在模块外使用导入语句 (Node.js) - TypeScript: Cannot use import statement outside a module (Node.js) 不能在模块外使用 import 语句 Electron React Typescript - Cannot use import statement outside a module Electron React Typescript 语法错误:不能在 typescript 中的模块外使用导入语句 - SyntaxError: Cannot use import statement outside a module in typescript SyntaxError:无法在模块 webpack-typescript 外使用 import 语句 - SyntaxError: Cannot use import statement outside a module webpack-typescript 无法在后端使用 typescript 的模块外部使用导入语句 - Cannot use import statement outside a module using typescript on backend Typescript 与 mocha - 无法在模块外使用导入语句 - Typescript with mocha - Cannot use import statement outside a module 使用 TypeScript 和 nodemon: SyntaxError: Cannot use import statement outside a module - Using TypeScript and nodemon: SyntaxError: Cannot use import statement outside a module Typescript &amp; TypeORM:不能在模块外使用导入语句 - Typescript & TypeORM: Cannot use import statement outside a module TypeScript/Knex:不能在模块外使用 import 语句 - TypeScript/Knex: Cannot use import statement outside a module SyntaxError:无法在 NodeJS Typescript 的模块外使用 import 语句 - SyntaxError: Cannot use import statement outside a module in NodeJS Typescript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM