ecmascript 6 - Typescript: Kan inte använda import-sats utanför en modul


Jag har en .ts-fil i en Node.js-app (senaste versionen av Node.js för 07.10.19) som importerar ett node-modul utan standardexport. Jag använder denna konstruktion: import { Class } from 'abc'; När jag kör koden får jag detta fel: Cannot use import statement outside a module.

På nätverket ser jag många lösningar för detta problem (för .js), men det hjälper mig inte, kanske för att jag har en TypeScript-fil. Här är min kod:

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

Här är min tsconfig.json:

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

    "strict": true
  }
}

Svar #1

Om du råkar använda ts-node kan du ställa in vissa kompilatoralternativ i tsconfig.json specifikt för ts-node att använda.

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

Då kan du bara köra ditt skript ganska enkelt:

ts-node my-script.ts

Svar #2

Uppdatering: Eftersom detta svar får betydande visningar har jag uppdaterat det för att bättre visa de tillgängliga lösningarna på detta problem år 2022.


Felet betyder att Node hittade ett import-uttalande i en fil som det inte anser vara en ECMAScript (ES) modul. Att lägga till "type": "module" i package.json kommer att tala om för Node att du använder ES-moduler, men då måste du tala om för TypeScript-kompilatorn att generera denna typ av modul genom att ställa in "module": "es2015" eller högre (till exempel: "es2020") i tsconfig.json. Om du vill generera CommonJS-moduler (require), ställ in "module": "commonjs".

Om du inte vill ställa in modulsystemet på projektnivå finns det mer detaljerade alternativ. Filer med .mjs-ändelsen behandlas alltid som ES-moduler, medan filer med .cjs alltid behandlas som CommonJS-moduler. Från och med TypeScript 4.5 är det också möjligt att använda .mts- och .cts-ändelser och låta kompilatorn generera .mjs- eller .cjs-filer, respektive.

De två systemen är delvis kompatibla. Till exempel är det möjligt att importera en CommonJS-modul till en ES-modul med en standardexport:

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

Tvärtom. Ett ES-modul kan importeras till en CommonJS-modul med dynamisk import (ES2020-funktioner behövs för att detta ska fungera):

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

Originalt svar (2020):

Att lägga till "type": "module" i package.json kommer att tala om för Node att du använder ES2015-moduler, vilket bör ta bort felet, men då måste du tala om för Typescript att generera denna typ av modul genom att sätta "module": "es2015" istället för "commonjs" i tsconfig.json.

Detta orsakar dock ett problem med den nuvarande koden eftersom även om du använder ett ES6 import {}-uttalande exporterar du med commonJS module.exports={}-syntaxen, och Nodes ES-modulladdare kommer att få problem med det. Det finns två sätt att hantera det:

  • Behåll module.exports men tala om för Node att tolka den här filen som commonJS genom att ge den en .cjs-förlängning.
  • Ändra export-satsen till ES2015-syntax: export function execute(…)..

Det första alternativet kan bli lite knepigt eftersom kompilatorn kommer att generera .js-filer och du skulle behöva ändra det till .cjs hela tiden (så vitt jag vet). Med det andra alternativet borde du kunna köra filen med Node (inklusive --experimental-modules-flaggan för versioner < 13.8).

Om du verkligen behöver använda commonJS, kanske det är bättre att installera typdefinitionerna för Node: @types/node och ändra importen till commonJS-format: require('abc') och behålla resten av inställningarna som de är (även om du kan lägga till "type": "commonjs" i package.json för att vara tydlig).

Svar #3

Se till att ditt "main"-fält i package.json pekar på den kompilerade index.js och inte på index.ts

Relaterade artiklar