Website-Suche

ecmascript 6 - Typescript: Kann Import-Anweisung außerhalb eines Moduls nicht verwenden


Ich habe eine .ts-Datei in einer Node.js-Anwendung (neueste Version von Node.js für den 07.10.19) mit dem Import eines Node-Moduls ohne Standardexport. Ich verwende diese Konstruktion: import { Class } from 'abc'; Wenn ich den Code ausführe, erhalte ich diesen Fehler: Cannot use import statement outside a module.

Im Netzwerk sehe ich viele Lösungen für dieses Problem (für .js), aber sie helfen mir nicht, vielleicht weil ich eine TypeScript-Datei habe. Hier ist mein Code:

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

Hier ist meine tsconfig.json:

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

    "strict": true
  }
}

Antwort #1

Wenn Sie zufällig ts-node verwenden, können Sie einige Compiler-Optionen in tsconfig.json festlegen, die speziell für die Verwendung von ts-node gedacht sind.

{
  "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"
  }
}

Dann kannst du dein Skript ziemlich einfach ausführen:

ts-node my-script.ts

Antwort #2

Update: Da diese Antwort viele Aufrufe erhält, habe ich sie aktualisiert, um die verfügbaren Lösungen für dieses Problem im Jahr 2022 besser zu zeigen.


Der Fehler bedeutet, dass Node eine import-Anweisung in einer Datei gefunden hat, die es nicht als ECMAScript (ES)-Modul betrachtet. Das Hinzufügen von "type": "module" zu package.json teilt Node mit, dass Sie ES-Module verwenden, aber dann müssen Sie dem TypeScript-Compiler mitteilen, diesen Modultyp auszugeben, indem Sie "module": "es2015" oder höher (zum Beispiel: "es2020") in tsconfig.json festlegen. Wenn Sie CommonJS-Module (require) ausgeben möchten, setzen Sie "module": "commonjs".

Falls Sie das Modulsystem nicht auf Projektebene einstellen möchten, gibt es feinere Optionen. Dateien mit der Endung .mjs werden immer als ES-Module behandelt, während Dateien mit .cjs immer als CommonJS-Module behandelt werden. Ab TypeScript 4.5 ist es ebenfalls möglich, die Endungen .mts und .cts zu verwenden und den Compiler .mjs- bzw. .cjs-Dateien erzeugen zu lassen.

Die beiden Systeme sind teilweise kompatibel. Zum Beispiel ist es möglich, ein CommonJS-Modul in ein ES-Modul mit einem Standardexport zu importieren:

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

Umgekehrt. Ein ES-Modul kann in ein CommonJS-Modul mit dynamischem Import importiert werden (ES2020-Funktionen werden benötigt, damit dies funktioniert):

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

Originalantwort (2020):

Das Hinzufügen von "type": "module" zu package.json teilt Node mit, dass Sie ES2015-Module verwenden, was den Fehler beseitigen sollte. Danach müssen Sie jedoch TypeScript mitteilen, diesen Modultyp zu erzeugen, indem Sie in tsconfig.json "module": "es2015" statt "commonjs" einstellen.

Dies verursacht jedoch ein Problem mit dem aktuellen Code, da Sie zwar eine ES6-import {}-Anweisung verwenden, jedoch mit der CommonJS-module.exports={}-Syntax exportieren, und der ES-Modul-Lader von Node ein Problem damit haben wird. Es gibt zwei Möglichkeiten, damit umzugehen:

  • Behalte das module.exports bei, aber sag Node, dass es diese Datei als CommonJS interpretieren soll, indem du ihr die Erweiterung .cjs gibst.
  • Ändere die Export-Anweisung auf ES2015-Syntax: export function execute(…)..

Die erste Option könnte etwas knifflig werden, weil der Compiler .js-Dateien ausgibt und man sie die ganze Zeit in .cjs ändern müsste (soweit ich weiß). Mit der zweiten Option solltest du in der Lage sein, die Datei mit Node auszuführen (einschließlich des --experimental-modules Flags für Versionen < 13.8).

Wenn Sie unbedingt CommonJS verwenden müssen, ist es vielleicht besser, die Typdefinitionen für Node zu installieren: @types/node und den Import auf das CommonJS-Format zu ändern: require('abc') und die restlichen Einstellungen so zu belassen, wie sie sind (obwohl Sie "type": "commonjs" zur package.json hinzufügen können, um es eindeutig zu machen).

Antwort #3

Stellen Sie sicher, dass Ihr "main"-Feld in package.json auf die kompilierte index.js und nicht auf die index.ts zeigt

Verwandte Artikel