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
