javascript - TypeScript ES6 uvoz modula "Datoteka nije modul"
Koristim TypeScript 1.6 sa sintaksom ES6 modula.
Moje datoteke su:
test.ts:
module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
}
main.ts:
import App from './test';
var a = new App.SomeClass();
Kad pokušavam kompajlirati datoteku main.ts, pojavljuje se ova pogreška:
Greška TS2306: Datoteka 'test.ts' nije modul.
Kako to mogu postići?
Odgovor #1
Prošireno - pružiti više detalja na temelju nekih komentara
Pogreška
Pogreška TS2306: Datoteka 'test.ts' nije modul.
Potiče iz činjenice opisane ovdje http://exploringjs.com/es6/ch_modules.html
17. Moduli
Ovo poglavlje objašnjava kako ugrađeni moduli rade u ECMAScript 6.
17.1 Pregled
U ECMAScript 6, moduli se pohranjuju u datoteke. U svakoj datoteci se nalazi točno jedan modul i jedna datoteka po modulu. Postoje dva načina za izvoz stvari iz modula. Ta dva načina mogu se miješati, ali obično je bolje koristiti ih odvojeno.
17.1.1 Višestruki imenovani exporti
Može postojati više imenovanih izvoznih elemenata:
//------ lib.js ------ export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diag(x, y) { return sqrt(square(x) + square(y)); } ...17.1.2 Jedan zadani izvoz
Može postojati jedan zadani izvoz. Na primjer, funkcija:
//------ myFunc.js ------ export default function () { ··· } // no semicolon!
Na temelju gore navedenog trebamo export, kao dio datoteke test.js. Prilagodimo sadržaj datoteke ovako:
// test.js - exporting es6
export module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
export class OtherClass {
getName(): string {
return 'name';
}
}
}
I sada ga možemo uvesti na ova tri načina:
import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";
I možemo konzumirati uvezene stvari poput ovih:
var a1: app1.App.SomeClass = new app1.App.SomeClass();
var a2: app1.App.OtherClass = new app1.App.OtherClass();
var b1: app2.App.SomeClass = new app2.App.SomeClass();
var b2: app2.App.OtherClass = new app2.App.OtherClass();
var c1: App.SomeClass = new App.SomeClass();
var c2: App.OtherClass = new App.OtherClass();
i pozovite metodu da je vidite u akciji:
console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())
Izvorni dio pokušava pomoći u smanjenju složenosti u korištenju prostora imena
Izvorni dio:
Snažno bih preporučio da provjerite ovo Pitanja i Odgovori:
Kako koristiti namespaceove s TypeScript vanjskim modulima?
Dopustite mi da citiram prvu rečenicu:
Ne koristite "prostore imena" u vanjskim modulima.
Nemoj to raditi.
Ozbiljno. Stani.
...
U ovom slučaju, jednostavno ne trebamo module unutar test.ts. Ovo bi mogao biti njegov sadržaj prilagođen test.ts:
export class SomeClass
{
getName(): string
{
return 'name';
}
}
Pročitajte više ovdje
Izvoz =
U prethodnom primjeru, kada smo koristili svaki validator, svaki modul je izvozio samo jednu vrijednost. U slučajevima poput ovog, zamorno je raditi s tim simbolima putem njihovog kvalificiranog imena kada bi dovoljan bio jedan identifikator.
Sintaksa
export =specificira jedan objekt koji se izvozi iz modula. To može biti klasa, sučelje, modul, funkcija ili enumeracija. Kada se uvozi, izvezeni simbol se koristi izravno i nije kvalificiran nijednim imenom.
kasnije ga možemo koristiti ovako:
import App = require('./test');
var sc: App.SomeClass = new App.SomeClass();
sc.getName();
Pročitajte više ovdje:
Neposredno učitavanje modula po izboru i drugi napredni scenariji učitavanja
U nekim slučajevima možda ćete željeti učitati modul samo pod određenim uvjetima. U TypeScriptu možemo koristiti obrazac prikazan u nastavku kako bismo to i druge napredne scenarije učitavanja implementirali za izravno pozivanje učitavača modula bez gubitka sigurnosti tipova.
Kompajler detektira koristi li se svaki modul u generiranom JavaScriptu. Za module koji se koriste samo kao dio sustava tipova, ne generiraju se pozivi require. Ovo uklanjanje nekorištenih referenci je dobra optimizacija performansi, a također omogućuje i opcionalno učitavanje tih modula.
Osnovna ideja obrasca je da nam naredba import id=require('...') omogućuje pristup tipovima koje izlaže vanjski modul. Učitavač modula se poziva (putem require) dinamički, kao što je prikazano u if blokovima ispod. Ovo koristi optimizaciju uklanjanja referenci tako da se modul učitava samo kada je potreban. Da bi ovaj obrazac funkcionirao, važno je da se simbol definiran putem import koristi samo u pozicijama za tipove (tj. nikada u poziciji koja bi bila emitirana u JavaScript).
Odgovor #2
Gornji odgovori su točni. Ali za svaki slučaj... Dobio sam istu pogrešku u VS Codeu. Morao sam ponovo spremiti/kompilirati datoteku koja je davala pogrešku.
Odgovor #3
Kako to mogu postići?
Vaš primjer deklarira TypeScript < 1.5 internal module, koji se sada naziva namespace. Stara module App {} sintaksa sada je ekvivalentna namespace App {}. Kao rezultat, sljedeće funkcionira:
// test.ts
export namespace App {
export class SomeClass {
getName(): string {
return 'name';
}
}
}
// main.ts
import { App } from './test';
var a = new App.SomeClass();
To rečeno...
Pokušajte izbjeći izvoz prostora imena i umjesto toga izvoziti module (koji su prije nazivali vanjski moduli). Ako je potrebno, možete koristiti prostor imena pri uvozu s obrascem uvoza prostora imena ovako:
// test.ts
export class SomeClass {
getName(): string {
return 'name';
}
}
// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();
Odgovor #4
Osim odgovora A. Tima, ponekad čak ni to ne djeluje, pa morate:
- Prepišite niz za uvoz koristeći intellisense. Ponekad to riješi problem
- Ponovno pokreni VS Code
