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
