Ich versuche, mein TypeScript-Projekt in JavaScript zu transpilieren, aber irgendetwas scheint nicht richtig zu sein. Ich habe das Projekt so konfiguriert, dass es als ES6-Modul (auch bekannt als ESM) über die "module":"ES6"
Einstellung, aber es löst das Problem nicht.
Das ist, was mein tsconfig.json
Konfiguration sieht so aus:
{
"compilerOptions": {
"module": "es6",
"target": "es6",
"lib": ["es6"],
"sourceMap": true,
}
}
Testfall mit einem Modulpaar:
Ich habe ein einfaches Testfall-Senario mit zwei Modulen geschrieben.
-
Das erste Modul — module1.ts
— exportiert nur eine Konstante, wie unten gezeigt:
-
Das zweite Modul – main.ts
— importiert nur den Export aus dem ersten Modul:
Die Ausgabedatei des zweiten Moduls (bzw main.js) ist in meine eingebettet index.html
Dokument, und ich habe das Typattribut als hinzugefügt type="module"
zum <script ...>
-Tag, wie unten gezeigt:
<script src="main.js" type="module"></script>
Wenn ich das mit beiden teste Feuerfuchs (dom.moduleScripts.enabled
ist in about:config gesetzt) oder Chrome Canary (Flag für experimentelle Webplattform ist gesetzt) es funktioniert nicht.
Der Typescript-Compiler scheint den TS zu transpilieren import { testText } from 'module1';
-Anweisung zur JS-Anweisung import { testText } from 'module1';
. (Anmerkung: beide sind genau gleich)
Die korrekte ES6-Importanweisung wäre:
import { testText } from 'module1.js';
(Beachten Sie die Dateierweiterung .js) Wenn ich die Dateierweiterung manuell zum generierten Code hinzufüge, funktioniert es.
Habe ich was falsch gemacht oder funktioniert das Typescript "module": "es6"
Die Einstellung funktioniert einfach nicht richtig? Gibt es eine Möglichkeit, den tsc so zu konfigurieren, dass den generierten Importanweisungen .js-Dateierweiterungen hinzugefügt werden?
Das ist ein verwirrende Designauswahl in TypeScript.
Kurzfristig können Sie dies umgehen, indem Sie die Ausgabedatei angeben:
in main.ts
Präzisiere das .js
Erweiterung und Pfad:
import { testText } from './module1.js';
alert(testText);
Das wird abgeholt module.ts
korrekt, aber mit der Ausgabe .js
Verlängerung enthalten.
Beachten Sie, dass Sie auch lokalen Dateien das Präfix voranstellen müssen ./
da „nackte“ Modulnamen für die zukünftige Verwendung reserviert sind.
HINWEIS DES AUTORS: „Das Datum, an dem diese Antwort veröffentlicht wurde, unterscheidet sich von dem Datum, an dem die Antwort ursprünglich erstellt wurde. Aufgrund von Änderungen in TypeScript musste ich zweimal eine neue Antwort schreiben. Da Daten in diesem Beitrag äußerst relevant sind, habe ich sie aufgenommen an einigen Stellen, für den Fall, dass die Antwort veraltet ist. Dies wird den Lesern helfen zu wissen, wann ich auf bestimmte Versionen von Technologien verwiesen habe, über die ich unten geschrieben habe.
Ursprünglich verfasst im Dezember 2022
Das “es-module-specifier” Flag-Fix für TS-, ESM- und NODE-Stacks
ESM war keine einfache Technologie, die in Node integriert werden konnte. Und als es darum ging, Node ES-Module in der TypeScript-Sprache zu schreiben, nun, das sah zu einem bestimmten Zeitpunkt tatsächlich so aus, als würde es niemals passieren. Meiner Meinung nach wollten bestimmte Projekte nicht das tun, was sie jetzt getan haben, um den Standard im Node-Back-End-RTE zu unterstützen. Wie auch immer, lass uns weitermachen…
Als ich diese Frage beantwortete, schlug ich zunächst vor, dass Personen, bei denen dieses Problem auftritt, das folgende Flag verwenden:
(FYI: Die Lösung kam von dem Link, der an das Snippet angehängt ist)
Die Flagge hat funktioniert, oder hat bis zu diesem Punkt als beste Lösung funktioniert (oder bis zu TS 4.7 Nightly Release). ES SOLLTE NOTIERT WERDEN Je nach Umgebung und Projekt, in dem Sie arbeiten, ist dies vorerst immer noch die beste Lösung.
Es wurde jedoch eine bessere Lösung verfügbar gemacht.
Zu diesem Zeitpunkt hat sich viel geändert:
Während der Nightly-Versionen von v4.6 TypeScript wurde Unterstützung für neue Modul- und moduleResolution-Spezifizierer hinzugefügt, die sind (“offensichtlich”) setzen in die tsconfig.json
. Sie wurden während der freigelassen v4.6
Nächtliche Builds, kurz bevor v4.6 Beta veröffentlicht wurde, und 4.7 wurde zum nächtlichen Build. Jetzt, v4.7
ist Beta und v4.8
ist der neue nächtliche Build (ich erwähne all diese Versionskram, nur um sicherzustellen, dass Sie auf dem neuesten Stand sind).
Dies sind die neuen Spezifizierer/Einstellungen, die uns TS gegeben hat
"module": "NodeNext"
"moduleResolution": "NodeNext"
Der Grund, warum ich das sage, ist, dass die neuen TSC-Flags (alias tsconfig-Einstellungen) in verfügbar waren v4.6
, was ich, wenn Sie sich erinnern, vor ein paar Absätzen gesagt habejedoch; Typoskript beschlossen, sie nicht in der aktuellen neuesten Version zu veröffentlichen (typescript@latest
) Version, die ist v4.6
. Sie werden also offiziell in TypeScript aufgenommen, wenn v4.7
befindet sich nicht mehr in der Beta-Phase und wird zur neuesten Version.
Sie sollten immer mit verwendet werden "esModuleInterop": true
(es sei denn, es ändert sich etwas an der “Node.js” Seite der Dinge. Das “esModuleInterop” Die Einstellung vereinfacht die Unterstützung für ESM, und einige der Knotenmodule benötigen sie, um ordnungsgemäß mit dem neuen ESM-Import/Export-Modulsystem zu funktionieren.
Das ist der ESM tsconfig.*.json
Konfigurationsvorlage, die ich jedem neuen Projekt als Ausgangspunkt hinzufüge.
"compilerOptions": {
// Obviously you need to define your file-system
"rootDir": "source",
"outDir": "build",
// THE SETTINGS BELOW DEFINE FEATURE SUPPORT, MODULE SUPPORT, AND ES-SYNTAX SUPPORT
"lib": ["ESNext"],
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true, // Eases ESM support
"types": ["node"],
"allowSyntheticDefaultImports": true,
}
Geschrieben am: 22. MAI 2022 8:50 Uhr PST
Gewinnung von Unterstützung für die module
& moduleResolution
Spezifizierer
Sie haben also ein paar verschiedene TS-Versionen, die Sie verwenden können, um die neuen Konfigurationen zu unterstützen. Sie können entweder verwenden Beta oder Nächtlich. Unten ist eine Tabelle, die die 3 verfügbaren Versionen zeigt. Stand jetzt, typescript@latest
ist @ v4.6
und unterstützt die neuen Konfigurationen nicht.
TS-FREIGABE |
AUSFÜHRUNG |
NPM-BEFEHL ZUM AUSFÜHREN |
HAT UNTERSTÜTZUNG? |
TS Neueste |
v4.6 |
npm i -D typescript@latest |
NEIN |
TS-Beta |
v4.7 |
npm i -D typescript@beta |
JAWOHL |
TS Nacht |
v4.8 |
npm i -D typescript@next |
JAWOHL |
Konfigurieren Sie Ihre Entwicklungsumgebung für die Verwendung der neuesten Ver
Sie müssen Ihre Umgebung für die Verwendung der neuen TypeScript-Version konfigurieren. Ich kann natürlich nicht die Konfiguration jedes Editors dokumentieren, aber VS-Code scheint am gebräuchlichsten zu sein Typoskriptund GEGEN 2022 verwendet eine ähnliche Konfiguration.
Im VS-Codefügen Sie Ihrem Arbeitsbereich die folgende Konfiguration hinzu ./.vscode/settings.json
Datei.
// "./.vscode/settings.json"
{ "typescript.tsdk": "./node_modules/typescript/lib",}
Konfigurieren Ihrer Laufzeitumgebung
(Was für diese Antwort Node.js ist)
Aber warum jD3V? Warum muss ich meine RTE konfigurieren? Was ist das Problem??? Macht die RTE jetzt nicht alles?
- Nein, die RTE weiß nicht einfach automatisch alles. Es muss irgendeine Art von Anweisungen oder Hinweisen haben.
**Aber haben wir das nicht schon konfiguriert tsconfig.json
Datei?
- Ja, aber das ist für TypeScript, jetzt müssen wir sicherstellen, dass der Knoten für unsere TS-Konfiguration bereit ist.
Wir müssen dem Knoten mitteilen, dass wir ein ECMAScript-Modul und kein CommonJS-Modul ausführen werden. Wir können dies auf zwei verschiedene Arten tun.
- Die erste besteht darin, unsere zu konfigurieren
package.json
Datei mit der package.json
Feld “Typ” der Konfigurationsdatei.
// @file "package.json"
{
"name": "project-name",
"version: "2.4.16",
"type": "module", // <-- Lets env know this project is an ESM
// the rest of your package.json file configuration...
}
-
Alternativ können Sie etwas wie oben tun, aber indem Sie die verwenden --input-type "module"
Flagge
-
Schließlich können Sie tun, was ich bevorzuge, und einfach jede Datei mit dem erstellen ESM Dateierweiterungen. In js ist es .ejs
und in Typoskript ist es .ets
.
Zum Beispiel wird Ihre Indexdatei sein index.ets
und TSC wird emittieren index.ejs
.
Schließlich ist es WICHTIG dass Sie verstehen, wie Importe beim Schreiben von an funktionieren “ES-Modul”. Ich werde einige Notizen auflisten, ich denke, das wird das beste Format für diese Informationen sein.
-
Beim Importieren von Dateien müssen Sie JavaScript-Dateierweiterungen verwenden.
-
ESM-Importe werden mit importiert URIs, und nicht durch die Verwendung von “possix filepaths”. Das Gegenteil war bei CJS-Modulen der Fall.
-
Sonderzeichen müssen prozentkodiert sein, wie # mit %23 und ? mit %3F.
-
TypeScript lässt Sie MimeType nicht voranstellen, aber ESM verwendet vorangestellte Datentypen, daher ist dies eine bewährte Vorgehensweise.
Beispielsweise ist es eine bewährte Methode, aus Knoten-APIs und Bibliotheken mit dem folgenden URI-Format zu importieren:
import EventEmitter from 'node:events';
const eEmit = new EventEmitter();
Keith hat richtig geantwortet.
In deiner main.ts
Anstatt von:
import { testText } from 'module1';
Versuche Folgendes:
import { testText } from 'module1.js';
In meinem Fall funktioniert vscode intellisense + ich bekomme die gewünschte Ausgabedatei main.js
auch.
Es ist ein bekanntes Problem, gemeldet als github.com/Microsoft/TypeScript/issues/13422 und github.com/Microsoft/TypeScript/issues/16577
– artem
7. Juli 2017 um 22:35 Uhr
Ich löse das gleiche Problem. Importieren
*.js
Datei ist eine nette Arbeit, aber dann hatte ich Probleme mit dem Refactoring in IDE (mit CLion) und dem Wechsel zu Deklaration, Definition usw. Also wechselte ich zurück zum Importieren ohne*.js
Erweiterung und eigentlich verwende ich SystemJS, um ES6 JavaScript zu transpilieren (als temporäre Lösung während der Entwicklung). Ich habe Informationen zur Verwendung des TypeScript-Compilers gefunden API. Ich denke an ein “benutzerdefiniertes” Build-Tool für diese Situation, aber eigentlich bin ich ziemlich beschäftigt. Wenn jemand ein paar Ideen, Anmerkungen oder so etwas wie t hat– Martin
30. August 2017 um 9:09 Uhr