ecmascript 6 - Typescript: Ne može se koristiti import izvan modula


Imam .ts datoteku u node js (najnovija verzija node.js za 07.10.19) aplikaciji s uvozom node modula bez zadane izvozne vrijednosti. Koristim ovu konstrukciju: import { Class } from 'abc'; Kada pokrenem kod, dobivam ovu pogrešku: Cannot use import statement outside a module.

Na mreži vidim mnogo rješenja za ovaj problem (za .js), ali mi ne pomaže, možda zato što imam TypeScript datoteku. Evo mog koda:

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

Evo mog tsconfig.json:

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

    "strict": true
  }
}

Odgovor #1

Ako slučajno koristite ts-node, možete postaviti neke opcije kompajlera u tsconfig.json posebno za korištenje 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"
  }
}

Tada možete jednostavno izvršiti svoj skript:

ts-node my-script.ts

Odgovor #2

Ažuriranje: Budući da ovaj odgovor dobiva značajan broj pregleda, ažurirao sam ga kako bih bolje prikazao dostupna rješenja za ovaj problem u 2022.


Greška znači da je Node pronašao import izjavu u datoteci koju ne smatra ECMAScript (ES) modulom. Dodavanje "type": "module" u package.json reći će Node-u da koristite ES module, ali tada ćete morati reći TypeScript kompajleru da emitira ovu vrstu modula postavljanjem "module": "es2015" ili više (na primjer: "es2020") u tsconfig.json. Ako želite emitirati CommonJS module (require), postavite "module": "commonjs".

U slučaju da ne želite postaviti sustav modula na razini projekta, postoje detaljnije opcije. Datoteke s nastavkom .mjs uvijek se tretiraju kao ES moduli, dok se datoteke s nastavkom .cjs uvijek tretiraju kao CommonJS moduli. Od verzije TypeScript 4.5 moguće je koristiti i nastavke .mts i .cts te omogućiti kompajleru da generira datoteke .mjs ili .cjs, redom.

Dva sustava su djelomično kompatibilna. Na primjer, moguće je uvesti CommonJS modul u ES modul s zadanim izvozom:

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

Obrnuto. ES modul se može uvesti u CommonJS modul pomoću dinamičkog uvoza (potrebne su ES2020 značajke da bi ovo radilo):

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

Izvorni odgovor (2020):

Dodavanje "type": "module" u package.json će reći Nodeu da koristite ES2015 module, što bi trebalo ukloniti pogrešku, ali tada ćete trebati reći Typescriptu da generira ovaj tip modula postavljanjem "module": "es2015" umjesto "commonjs" u tsconfig.json.

Ovo ipak uzrokuje problem s trenutnim kodom jer iako koristite ES6 import {} izjavu, izvozite koristeći commonJS module.exports={} sintaksu, a Nodeov ES modul loader će imati problema s tim. Postoje dva načina kako to riješiti:

  • Zadrži module.exports, ali reci Node-u da interpretira ovu datoteku kao commonJS tako što ćeš joj dati .cjs ekstenziju.
  • Promijenite izvoznu izjavu na ES2015 sintaksu: export function execute(…)..

Prva opcija bi mogla postati malo komplicirana jer će kompajler izlaziti .js datoteke i morali biste ih stalno mijenjati u .cjs (koliko ja znam). S drugom opcijom trebali biste moći pokrenuti datoteku s Node (uključujući zastavicu --experimental-modules za verzije < 13.8).

Ako apsolutno morate koristiti commonJS, možda je bolje instalirati definicije tipova za Node: @types/node i promijeniti uvoz u commonJS format: require('abc') i zadržati ostale postavke kako jesu (iako možete dodati "type": "commonjs" u package.json kako biste to izričito naznačili).

Odgovor #3

Provjerite je li vaše polje "main" u package.json usmjereno na kompajlirani index.js, a ne na index.ts

Povezani članci