Ich habe einige TypeScript-Dateien:
MyClass.ts
class MyClass {
constructor() {
}
}
export = MyClass;
MyFunc.ts
function fn() { return 0; }
export = fn;
MyConsumer.ts
import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();
Dies gibt mir Fehler beim Versuch zu verwenden new
Das Modul "MyClass" wird in eine Nicht-Modul-Entität aufgelöst und kann mit diesem Konstrukt nicht importiert werden.
und beim Versuch anzurufen fn()
Ein Ausdruck, dessen Typ keine Anrufsignatur hat, kann nicht aufgerufen werden.
Was gibt?
typescript
ecmascript-6
es6-modules
Ryan Cavanaugh
quelle
quelle
javascript
als primäres Tag zu entfernen und zu verlassenecmascript-6
, da das primäre Tag hier isttypescript
. Die Frage geht fälschlicherweise davon aus, dassexport =
(eine TS-Funktion) mit gepaart werden kannimport ... from
, während sie gepaart werden sollteimport =
. Es handelt sich im Grunde genommen um den Import / Export von ES6-Modulen im Vergleich zu CJS / AMD.Antworten:
Warum es nicht funktioniert
Dies ist eine ES6 / ES2015-
import
Syntax. Die genaue Bedeutung lautet "Nehmen Sie das geladene Modul- Namespace-Objekt./MyClass
und verwenden Sie es lokal alsMC
". Insbesondere besteht das "Modul- Namespace-Objekt " nur aus einem einfachen Objekt mit Eigenschaften. Ein ES6-Modulobjekt kann nicht als Funktion oder mit aufgerufen werdennew
.Um es noch einmal zu sagen: Ein ES6-Modul-Namespace-Objekt kann nicht als Funktion oder mit aufgerufen werden
new
.Das , was Sie
import
mit* as X
von einem Modul definierten Eigenschaften nur haben. In CommonJS mit niedrigerem Level wird dies möglicherweise nicht vollständig berücksichtigt, aber TypeScript sagt Ihnen, wie sich der Standard verhält.Was funktioniert?
Sie müssen die CommonJS-artige Importsyntax verwenden, um dieses Modul zu verwenden:
Wenn Sie beide Module steuern, können Sie
export default
stattdessen Folgendes verwenden:MyClass.ts
MyConsumer.ts
Ich bin traurig darüber; Regeln sind dumm.
Es wäre schön gewesen, die ES6-Importsyntax zu verwenden, aber jetzt muss ich das tun
import MC = require('./MyClass');
? Es ist so 2013! Lame! Aber Trauer ist ein normaler Bestandteil der Programmierung. Bitte springen Sie im Kübler-Ross-Modell zur fünften Stufe: Akzeptanz.TypeScript hier sagt Ihnen, dass dies nicht funktioniert, weil es nicht funktioniert. Es gibt Hacks (das Hinzufügen einer
namespace
Deklaration zuMyClass
ist eine beliebte Methode, um so zu tun, als ob dies funktioniert), und sie funktionieren möglicherweise heute in Ihrem speziellen Downleveling-Modulbündler (z. B. Rollup), aber dies ist illusorisch. Es gibt noch keine ES6-Modulimplementierungen in freier Wildbahn, aber das wird nicht für immer so sein.Stellen Sie sich Ihr zukünftiges Ich vor, versuchen Sie, auf einer nativen ES6-Modulimplementierung zu arbeiten, und stellen Sie fest, dass Sie sich auf einen schwerwiegenden Fehler eingestellt haben, indem Sie versuchen, mithilfe der ES6-Syntax etwas zu tun, was ES6 explizit nicht tut .
Ich möchte meinen nicht standardmäßigen Modullader nutzen
Möglicherweise haben Sie einen Modullader, der "hilfreich"
default
Exporte erstellt, wenn keine vorhanden sind. Ich meine, Leute machen Standards aus einem bestimmten Grund, aber Standards zu ignorieren macht manchmal Spaß und wir können denken, dass das eine coole Sache ist.Ändern Sie MyConsumer.ts in:
Und geben Sie die
allowSyntheticDefaultImports
Befehlszeile odertsconfig.json
Option an.Beachten Sie, dass
allowSyntheticDefaultImports
dies das Laufzeitverhalten Ihres Codes überhaupt nicht ändert. Es ist nur ein Flag, das TypeScript mitteilt, dass Ihr Modulladerdefault
Exporte erstellt, wenn keine vorhanden sind. Es wird Ihren Code nicht auf magische Weise in NodeJS funktionieren lassen, wenn dies vorher nicht der Fall war.quelle
export = MyClass
? Meine einzige Möglichkeit besteht darin, mein Modul so einzustellencommonjs
, dass die Welt schlechter wird, indem ich kein modernes ES verwende.--esModuleInterop
"Wir empfehlen dringend, es sowohl auf neue als auch auf bestehende Projekte anzuwenden". Meiner Meinung nach sollte diese Antwort (und der FAQ-Eintrag / die FAQ-Richtlinie inDefinitelyTyped
diesen Links hier) geändert werden, um die neue Haltung widerzuspiegeln.TypeScript 2.7 bietet Unterstützung durch die Ausgabe neuer Hilfsmethoden: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form- commonjs-modules-with --- esmoduleinterop
Fügen Sie in tsconfig.json diese beiden Einstellungen hinzu:
Und jetzt können Sie verwenden:
quelle
esModuleInterop
ichresolveJsonModule
neben Ihrem anderen Vorschlag verwendet,allowSyntheticDefaultImports
und es hat bei mir funktioniert.Das Hinzufügen meiner 2 Cent hier, falls jemand anderes dieses Problem hat.
Bei meiner Art, das Problem zu umgehen, ohne es zu ändern
tsconfig.json
(was in einigen Projekten problematisch sein kann), habe ich die Regel für Online einfach deaktiviert.import MC = require('./MyClass'); // tslint:disable-line
quelle
Ich habe diesen Fehler erhalten, als ich versucht habe, ein npm-Debounce-Paket in mein Projekt aufzunehmen.
Als ich die oben akzeptierte Lösung ausprobierte, bekam ich eine Ausnahme:
Das hat funktioniert:
quelle