Typescript es6 import module "Il file non è un errore del modulo"


127

Sto usando il dattiloscritto 1.6 con la sintassi dei moduli es6.

I miei file sono:

test.ts:

module App {
  export class SomeClass {
    getName(): string {
      return 'name';
    }
  }
}

main.ts:

import App from './test';

var a = new App.SomeClass();

Quando provo a compilare il main.tsfile ottengo questo errore:

Errore TS2306: il file 'test.ts' non è un modulo.

Come posso farlo?


Ho avuto questo problema, non avevo un costruttore in classe, ne ho aggiunto uno e il problema è andato via
dorriz

Risposte:


139

Esteso : per fornire maggiori dettagli sulla base di alcuni commenti

L'errore

Errore TS2306: il file 'test.ts' non è un modulo.

Viene dal fatto descritto qui http://exploringjs.com/es6/ch_modules.html

17. Moduli

Questo capitolo spiega come funzionano i moduli integrati in ECMAScript 6.

17.1 Panoramica

In ECMAScript 6, i moduli sono memorizzati in file. Esiste esattamente un modulo per file e un file per modulo. Hai due modi per esportare cose da un modulo. Questi due modi possono essere mescolati, ma di solito è meglio usarli separatamente.

17.1.1 Esportazioni con più nomi

Possono esserci più esportazioni denominate:

//------ 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 Esportazione predefinita singola

Può esserci un'unica esportazione predefinita. Ad esempio, una funzione:

//------ myFunc.js ------
export default function () { ··· } // no semicolon!

Sulla base di quanto sopra abbiamo bisogno export, come parte del file test.js. Adattiamo il contenuto in questo modo:

// test.js - exporting es6
export module App {
  export class SomeClass {
    getName(): string {
      return 'name';
    }
  }
  export class OtherClass {
    getName(): string {
      return 'name';
    }
  }
}

E ora possiamo importarlo in questi tre modi:

import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";

E possiamo consumare cose importate come questa:

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();

e chiama il metodo per vederlo in azione:

console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())

La parte originale sta cercando di aiutare a ridurre la quantità di complessità nell'uso dello spazio dei nomi

Parte originale:

Consiglio vivamente di controllare queste domande e risposte:

Come uso gli spazi dei nomi con i moduli esterni TypeScript?

Vorrei citare la prima frase:

Non utilizzare "spazi dei nomi" in moduli esterni.

Non farlo

Sul serio. Fermare.

...

In questo caso, non abbiamo solo bisogno di moduledentro test.ts. Questo potrebbe essere il contenuto adattato test.ts:

export class SomeClass
{
    getName(): string
    {
        return 'name';
    }
}

Leggi di più qui

Esporta =

Nell'esempio precedente, quando abbiamo utilizzato ciascun validatore, ciascun modulo ha esportato un solo valore. In casi come questo, è ingombrante lavorare con questi simboli attraverso il loro nome qualificato quando anche un singolo identificatore farebbe altrettanto.

La export =sintassi specifica un singolo oggetto che viene esportato dal modulo . Può essere una classe, un'interfaccia, un modulo, una funzione o un enum. Quando viene importato, il simbolo esportato viene utilizzato direttamente e non è qualificato con alcun nome.

possiamo successivamente consumarlo in questo modo:

import App = require('./test');

var sc: App.SomeClass = new App.SomeClass();

sc.getName();

Leggi di più qui:

Caricamento del modulo opzionale e altri scenari di caricamento avanzato

In alcuni casi, potresti voler caricare un modulo solo in alcune condizioni. In TypeScript, possiamo usare il modello mostrato di seguito per implementare questo e altri scenari di caricamento avanzati per invocare direttamente i caricatori di moduli senza perdere la sicurezza del tipo.

Il compilatore rileva se ogni modulo viene utilizzato nel JavaScript emesso. Per i moduli che vengono utilizzati solo come parte del sistema di tipi, non è necessario emettere chiamate. Questa selezione di riferimenti non utilizzati è una buona ottimizzazione delle prestazioni e consente anche il caricamento opzionale di tali moduli.

L'idea principale del modello è che l'istruzione import id = require ('...') ci dà accesso ai tipi esposti dal modulo esterno. Il loader del modulo viene invocato (tramite request) in modo dinamico, come mostrato nei blocchi if seguenti. Ciò sfrutta l'ottimizzazione dell'abbattimento dei riferimenti in modo che il modulo venga caricato solo quando necessario. Perché questo modello funzioni, è importante che il simbolo definito tramite import venga utilizzato solo nelle posizioni di tipo (ovvero mai in una posizione che verrebbe emessa nel JavaScript).


1
Ma questo: import App = request ('./ test'); non è la sintassi dei moduli es6. questo è js comune. Posso farlo con la sintassi dei moduli es6?
Bazinga,

@JsIsAwesome Stai provando a mescolare i moduli JS con i moduli Typescript. Devi usare l'uno o l'altro, non una combinazione di entrambi.
JJJ,

Questa risposta non si riferisce alla sintassi ES6
phiresky

@phiresky, che vuoi dire?
Radim Köhler,

1
Grazie, fantastico.
phiresky,

24

Le risposte sopra sono corrette. Ma per ogni evenienza ... Ho avuto lo stesso errore in VS Code. Ho dovuto ri-salvare / ricompilare il file che stava generando un errore.


3
Questo ha funzionato per me. Ho semplicemente rimosso un punto e virgola, l'ho aggiunto di nuovo e salvato di nuovo il file, quindi l'esecuzione di Webpack ha funzionato. Ottimo momento per essere vivi.
Ray Hogan,

1
Sono abituato a Webstorm e non ho realizzato che i file non venivano salvati automaticamente in VS Code. Questa risposta mi ha risparmiato molto dolore, grazie.
cib

C'è un'impostazione per il salvataggio automatico in VS Code. Non lo uso perché VS Code esegue già il backup dei file non salvati e non uso sempre git.
aamarks,

13

Come posso farlo?

Il tuo esempio dichiara un modulo interno TypeScript <1.5 , che ora viene chiamato spazio dei nomi . La vecchia module App {}sintassi è ora equivalente a namespace App {}. Di conseguenza, funziona come segue:

// test.ts
export namespace App {
    export class SomeClass {
        getName(): string {
            return 'name';
        }
    }
}

// main.ts
import { App } from './test';
var a = new App.SomeClass();

Detto ciò...

Cerca di evitare l'esportazione di spazi dei nomi e invece di esportare moduli (che in precedenza erano chiamati moduli esterni ). Se necessario, è possibile utilizzare uno spazio dei nomi durante l'importazione con il modello di importazione dello spazio dei nomi in questo modo:

// test.ts
export class SomeClass {
    getName(): string {
        return 'name';
    }
}

// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();

1
È ancora una buona pratica? Secondo questa risposta ( stackoverflow.com/a/35706271/2021224 ), tentare di importare una funzione o una classe come questa e quindi invocarla - "è illegale secondo le specifiche ES6".
Andrey Prokhorov,

2

Oltre alla risposta di A. Tim, ci sono momenti in cui anche quello non funziona, quindi è necessario:

  1. Riscrivi la stringa di importazione, usando l'intellisense. A volte questo risolve il problema
  2. Riavvia il codice VS.

1
lo stesso per stackblitz - file ricompilato che importa il modulo e tutto funziona bene, evviva
godblessstrawberry

L'ho provato anche quando il mio codice non è stato formattato correttamente. VSCode ha indentato il mio codice di classe copia + incolla mentre dividevo le mie classi nei propri file e VSCode ha indentato tutto ciò export class... {che non era gradito, cosa che angolare non mi piaceva, dandomi questo problema. Dopo aver corretto la formattazione, compilato senza problemi.
Guy Park,

0

Oltre alla risposta di Tim, questo problema si è verificato durante la suddivisione di un refactoring di un file, suddividendolo nei propri file.

VSCode, per qualche motivo, ha indentato parti del mio codice [class], che ha causato questo problema. Inizialmente è stato difficile accorgersene, ma dopo aver realizzato che il codice era rientrato, ho formattato il codice e il problema è scomparso.

ad esempio, tutto ciò che segue la prima riga della definizione di classe è stato rientrato automaticamente durante l'incolla.

export class MyClass extends Something<string> {
    public blah: string = null;

    constructor() { ... }
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.