Zum Inhalt springen
Aback Tools Logo

TypeScript-Fehler TS1384: Ursache und Lösung

Behebe den TypeScript-Fehler TS1384 („Der Modifizierer export kann nicht auf eine Modulerweiterung angewendet werden"). Die drei Ursachen, der export-{}-Fix, isolatedModules und .d.ts-Muster.

DH
Tutorials & How-Tos11 Min. Lesezeit2,650 Wörter

Der TypeScript-Fehler TS1384 gehört zu denen, die beim ersten Kontakt kryptisch wirken, aber immer eine präzise und behebbare Ursache haben. Er tritt auf, wenn der Compiler einen export-Modifizierer an einer Stelle findet, an der er nicht stehen darf – genauer gesagt innerhalb eines Modulerweiterungs-Blocks. Dieser Leitfaden erklärt genau, was TS1384 bedeutet, geht jedes auslösende Szenario durch und nennt für jedes die richtige Lösung.

TS1384FehlercodeExport in Modulerweiterung
1 ZeileTypischer Fixexport {} löst die meisten Fälle
3UrsachenSkript, isolatedModules, .d.ts

Was ist TS1384?

Der TypeScript-Fehler TS1384 trägt die Meldung: „Der Modifizierer 'export' kann nicht auf eine Modulerweiterung angewendet werden." Er tritt auf, wenn der Compiler das Schlüsselwort `export` in einem `declare module`- oder `declare global`-Block findet – den beiden Konstrukten, die TypeScript für Modulerweiterungen nutzt. Erweiterungsblöcke dienen dem Erweitern bestehender Modultypen, nicht dem Deklarieren neuer öffentlicher Symbole; `export` ist darin daher strukturell ungültig.

Modulerweiterung in einem Satz

Modulerweiterung ist der TypeScript-Mechanismus, mit dem du neuen Mitglieder zu den Typen eines bestehenden Moduls hinzufügen kannst – zum Beispiel eine eigene Eigenschaft zu `Express.Request`, eine Erweiterung von `Window` um ein Fremd-Global oder zusätzliche Methoden in den Komponentenoptionen eines Frameworks. Die Syntax sieht wie ein `declare module 'modulname' {}`-Block aus und muss in einer Moduldatei stehen (einer Datei mit mindestens einer `import`- oder `export`-Anweisung auf oberster Ebene).

  • TS1384 ist ein Compilerfehler – die Datei wird nicht typgeprüft, bis er behoben ist
  • Er betrifft die Laufzeit nicht – der Fehler betrifft ausschließlich Typdeklarationen
  • Er ist deterministisch – derselbe Code löst ihn immer aus; es gibt keine sporadische Variante
  • Er hat wenige Ursachen – Skript- vs. Modulkontext, isolatedModules und falsche .d.ts-Struktur decken 95 % der Fälle ab

Note

TS1384 ist verwandt mit, aber verschieden von TS2669 („Erweiterungen des globalen Gültigkeitsbereichs können nur direkt in externen Modulen oder Ambient-Moduldeklarationen verschachtelt werden"). Beide entstehen aus einem falschen Dateikontext für die Erweiterungssyntax und beide werden mit derselben `export {}`-Technik behoben – jedoch wird TS2669 durch die Position des `declare global`-Blocks ausgelöst, während TS1384 speziell durch einen `export`-Modifizierer innerhalb der Erweiterung ausgelöst wird.

Wann TS1384 auftritt

Der Fehler betrifft immer ein `export` an einer Stelle, an der TypeScript es nicht zulässt. Es gibt drei verschiedene Muster, die ihn erzeugen; zu erkennen, welches auf deine Codebasis zutrifft, bestimmt den richtigen Fix.

Muster 1 – export in einem declare-module-Block

Der direkteste Auslöser: Du schreibst eine `export`-Anweisung in eine `declare module`-Erweiterung. Die Absicht ist meist, etwas zur öffentlichen API des Moduls hinzuzufügen, aber Erweiterungsblöcke funktionieren nicht so – sie können nur Typdeklarationen erweitern, die im Zielmodul bereits existieren.

typescript
// ✗ TS1384 - export innerhalb einer Modulerweiterung
declare module 'some-library' {
  export interface NewInterface {   // <-- hier wird TS1384 ausgelöst
    id: string;
  }
}

// ✓ Korrekt - Interface ohne export hinzugefügt
declare module 'some-library' {
  interface ExistingInterface {
    newProperty: string;            // erweitert den vorhandenen Typ
  }
}

Muster 2 – die Datei gilt als Skript, nicht als Modul

Das ist die häufigste Ursache für TS1384 in echten Projekten. Hat eine Datei keine `import`- oder `export`-Anweisungen auf oberster Ebene, behandelt TypeScript sie als Skript mit globalem Gültigkeitsbereich. Ein `declare global {}`-Block in einer Skriptdatei ist sinnlos – in Skripten ist bereits alles global –, deshalb lehnt TypeScript jedes `export` darin mit TS1384 ab. Die Datei muss ein Modul sein, damit der Erweiterungskontext Sinn ergibt.

Muster 3 – falsche Struktur der .d.ts-Datei

Deklarationsdateien (`.d.ts`), die Ambient-Moduldeklarationen und reguläre export-Anweisungen in der falschen Reihenfolge mischen, können TS1384 auslösen. Eine `.d.ts`, die mit `export`-Deklarationen auf oberster Ebene beginnt und danach einen `declare module`-Block enthält, gilt als Modul – das ist korrekt. Eine `.d.ts` dagegen, die alles in einen einzigen `declare module`-Block packt und dann innerhalb dieses Blocks `export` verwendet, verwechselt den Erweiterungskontext mit einem Moduldefinitionskontext.

Warning

TS1384 kann auch aus einem **Fremdpaket** stammen, das defekte `.d.ts`-Dateien ausliefert. Wenn der Fehler auf einen Pfad innerhalb von `node_modules` zeigt, liegt die Quelle in einer Abhängigkeit, nicht in deinem Code. Der Fix ist dann `skipLibCheck: true` in der tsconfig.json, nicht das Bearbeiten der Paketdateien.

TS1384 beheben: Modulerweiterung

Die richtige Lösung hängt davon ab, was du eigentlich erreichen willst. Zwei unterschiedliche Ziele können zu TS1384 führen und verlangen unterschiedliche Vorgehensweisen. Diese vier Schritte lösen den Fehler sauber auf.

1

Ermittle, welches Muster TS1384 auslöst

Lies die vollständige Compiler-Meldung sorgfältig. Achte auf die Dateiendung (.ts oder .d.ts), die Zeilennummer und darauf, ob das `export` in einem `declare module`-Block, einem `declare global`-Block oder woanders steht. Der umgebende Codekontext verrät dir, welches der drei Muster oben zutrifft. Beginnt der Fehlerpfad mit `node_modules/`, springe direkt zum `skipLibCheck`-Fix – die anderen Muster greifen dort nicht.

2

export {} hinzufügen, um die Datei in ein Modul umzuwandeln

Enthält deine Datei einen `declare module`- oder `declare global`-Block, aber keine Imports oder Exports auf oberster Ebene, füge oben `export {}` hinzu. Diese eine Zeile wandelt die Datei vom Skript- in den Modulkontext um – die Voraussetzung für die Erweiterungssyntax. Der leere Export fügt der kompilierten Ausgabe nichts hinzu; er ist reines Kontextsignal für TypeScript.

src/types/global.d.ts
typescript
// Diese Zeile macht die Datei zu einem Modul
export {};

declare global {
  interface Window {
    myAnalytics: AnalyticsInstance;
  }
}
3

declare global in ein vorhandenes Modul verschieben

Eine Alternative zu `export {}` ist, den `declare global`-Block in eine Datei zu legen, die bereits echte Imports oder Exports hat – etwa den Einstiegspunkt einer Bibliothek, ein Feature-Modul oder eine gemeinsame Utility-Datei. So bleiben deine Typ-Erweiterungen beim Code, den sie erweitern, was leichter zu pflegen sein kann als eine eigene Datei für globale Deklarationen.

4

export aus dem Erweiterungsblock entfernen

Wenn du tatsächlich einen neuen exportierbaren Typ zur öffentlichen API eines bestehenden Moduls hinzufügen willst, ist der Erweiterungsblock der falsche Ort. Verschiebe die Deklaration vollständig aus dem `declare module`-Block heraus. Um ein vorhandenes Interface zu erweitern, verwende denselben Interface-Namen ohne `export` innerhalb des Blocks – TypeScript führt ihn über Declaration Merging automatisch zusammen.

JSON-Formatierer und -Validator

Prüfe deine tsconfig.json und package.json sofort im Browser auf Syntaxfehler – ganz ohne TypeScript-Compiler.

Open tool

TS1384 und isolatedModules

Die Compiler-Option `isolatedModules` ist standardmäßig in Vite, Next.js, Create React App mit Babel und jedem Projekt mit esbuild oder SWC aktiv. Sie verlangt, dass jede Datei ohne dateiübergreifende Typinformationen unabhängig transformierbar ist, was Einschränkungen schafft, die mehrere TypeScript-Fehler verstärken – darunter TS1384.

Was isolatedModules einschränkt

KonstruktOhne isolatedModulesMit isolatedModules
`const enum`✓ Überall erlaubt✗ Nur in .d.ts-Dateien
`export type`✓ Optional✓ Pflicht für reine Typ-Re-Exports
`import type`✓ Optional✓ Pflicht für reine Typ-Imports
Ambient-Deklarationen✓ In jeder .ts-Datei✓ Besser in .d.ts-Dateien
Modulerweiterung✓ In Modul-.ts-Dateien✓ Bevorzugt in .d.ts-Dateien
Namespace-Re-Exports✓ Erlaubt✗ Eingeschränkt

Der spezifische Fix für isolatedModules

Wenn `isolatedModules` aktiv ist und TS1384 bei einer Erweiterung in einer regulären `.ts`-Datei auftritt, ist der sauberste Fix, die Erweiterung in eine `.d.ts`-Datei zu verschieben. Deklarationsdateien werden nie von esbuild oder Babel transformiert – sie liest nur der TypeScript-Compiler. Damit entfällt die isolatedModules-Einschränkung für diese Erweiterung vollständig.

src/types/express.d.ts
typescript
// Dieses Muster funktioniert korrekt mit isolatedModules
export {};

declare module 'express' {
  interface Request {
    userId?: string;
    tenantId?: string;
  }
}

Tip

Wenn du nicht sicher bist, ob `isolatedModules` in deinem Projekt aktiv ist, suche in der tsconfig.json nach `"isolatedModules": true`. Ein Blick in die Bundler-Konfiguration hilft ebenfalls: Vites Standard-tsconfig enthält die Option, und Next.js aktiviert sie bei Nutzung von SWC automatisch. Nutze den [Diff-Viewer](/tools/data/dev-utilities/diff-viewer), um deine tsconfig mit einer bekannten Referenz zu vergleichen, wenn du umgebungsspezifische TS1384-Probleme analysierst.

TS1384 in .d.ts-Dateien

Deklarationsdateien bringen eigene Feinheiten in TS1384. Die Regeln dafür, was in einer `.d.ts`-Datei gültig ist, unterscheiden sich leicht von regulären `.ts`-Dateien, und die Muster, die TS1384 in Deklarationsdateien erzeugen, sind oft weniger intuitiv.

Ambient-Moduldefinition oder Erweiterung?

Eine `.d.ts`-Datei kann zwei grundlegend verschiedene Dinge enthalten, die ähnlich aussehen, sich aber anders verhalten. Eine Ambient-Moduldefinition (`declare module 'name' {}` in einer `.d.ts` im Skriptkontext, ohne Imports oder Exports) definiert alle Typen eines Moduls von Grund auf – sie wird verwendet, um untypisierte JavaScript-Bibliotheken zu typisieren. Eine Modulerweiterung (`declare module 'name' {}` in einer `.d.ts` im Modulkontext mit `export {}`) erweitert die Typen eines bestehenden Moduls. Die Unterscheidung ist wichtig, weil `export` in einer Ambient-Moduldefinition gültig ist, in einer Modulerweiterung jedoch TS1384 erzeugt.

Das richtige .d.ts-Muster wählen

Wenn deine `.d.ts`-Datei Typen für eine untypisierte Bibliothek definiert (z. B. ein altes jQuery-Plugin typisiert), lass sie im Skriptkontext ohne `export {}` am Anfang. Verwende `export` im `declare module`-Block frei. Wenn deine `.d.ts`-Datei eine bereits typisierte Bibliothek erweitert (z. B. eine Eigenschaft zu `Express.Request` hinzufügt), füge oben `export {}` hinzu und entferne jedes `export` aus dem `declare module`-Block.

Note

Eine schnelle Faustregel: Hat das Zielmodul bereits Typdefinitionen (über `@types/...` oder integriert), erweiterst du es. Hat es überhaupt keine Typen und du erstellst sie von Grund auf, schreibst du eine Ambient-Moduldefinition.

skipLibCheck als letztes Mittel

Wenn TS1384 auf einem Pfad innerhalb von `node_modules` auftritt und du das Paket nicht kontrollierst, füge `"skipLibCheck": true` in deine tsconfig.json ein. Das weist TypeScript an, die Typprüfung aller `.d.ts`-Dateien zu überspringen – auch derer in `node_modules`. Es ist eine legitime, weit verbreitete Konfigurationsoption, kein Hack. Der Preis: Du verlierst die Typprüfung der Bibliotheksdeklarationen vollständig, sodass wirklich kaputte Typen in Abhängigkeiten unbemerkt bleiben. Nutze `skipLibCheck` nur, wenn die Alternative darin besteht, deinen Build zu blockieren.

TS1384 in Frameworks und Bundlern

Jedes Framework und Build-Tool konfiguriert TypeScript anders, weshalb TS1384 je nach Stack aus leicht unterschiedlichen Gründen auftreten kann. So entsteht und verschwindet der Fehler in den gängigsten Umgebungen.

Next.js

Next.js aktiviert `isolatedModules` über seine Standard-tsconfig automatisch und nutzt SWC für die Transformation. Das Standardmuster für Typerweiterungen in Next.js ist ein eigenes `types/`-Verzeichnis im Projektstamm mit `.d.ts`-Dateien, die mit `export {}` beginnen. Next.js erzeugt außerdem eine `next-env.d.ts` – bearbeite diese Datei nie manuell, da sie bei jedem Build neu erzeugt wird und deine Änderungen verloren gehen. Lege deine Erweiterungen in einer separaten Datei ab.

Vite

Vite-Projekte nutzen esbuild für die Transformation und enthalten `isolatedModules: true` in der Standard-tsconfig. Vite erzeugt zudem eine `vite-env.d.ts` für eigene Globals. Lege Modulerweiterungen in einem separaten `src/types/`-Verzeichnis ab. Das `export {}`-Muster behebt TS1384 in allen Standard-Vite-Setups, und Erweiterungen in `.d.ts`-Dateien zu halten ist der sicherste Ansatz, wenn die esbuild-Transformation in der Kette liegt.

Reine Node.js-/Express-APIs

Express-Projekte erweitern häufig `Express.Request`, um Nutzersitzung oder Auth-Kontext hinzuzufügen. Das kanonische Muster ist eine Datei `src/types/express/index.d.ts` mit `export {}` am Anfang, gefolgt von der Erweiterung `declare module 'express-serve-static-core'`. Ohne `isolatedModules` funktioniert das auch als reguläre `.ts`-Datei – die `.d.ts`-Variante ist jedoch in jedem Fall die sauberere Konvention. Prüfe immer den exakten Modulnamen in den Express-Typdefinitionen, denn das Erweiterungsziel ist `express-serve-static-core`, nicht `express`.

Die Datei muss ein Modul sein, bevor sie eines erweitern kann. Ein einziges `export {}` macht aus einem Skript ein Modul – und schaltet das gesamte Erweiterungssystem frei.

- Prinzip der TypeScript-Modulerweiterung

TS1384 langfristig vermeiden

TS1384 entsteht leicht versehentlich, besonders wenn neue Teammitglieder Typerweiterungen hinzufügen oder du ein Projekt auf einen neuen Bundler umstellst. Diese Praktiken verhindern, dass er nach der Behebung zurückkehrt.

Eine Konvention für das Types-Verzeichnis etablieren

Lege ein Verzeichnis `src/types/` (oder `types/`) an und bewahre dort alle Modulerweiterungen als `.d.ts`-Dateien auf. Jede Datei sollte eine Erweiterung enthalten und mit `export {}` beginnen. Dokumentiere diese Konvention im `CONTRIBUTING.md` deines Projekts, damit neue Beitragende wissen, wohin Typdeklarationen gehören. Ein einheitlicher Ort erleichtert zudem die Prüfung der Erweiterungen bei Abhängigkeits-Upgrades.

tsc --noEmit in der CI nutzen

Ein CI-Schritt mit `tsc --noEmit` erkennt TS1384 (und jeden anderen TypeScript-Fehler), bevor Code den main-Branch erreicht. Viele Projekte überspringen die Typprüfung in der CI, weil ihr Bundler sie nicht verlangt – esbuild und SWC entfernen Typen, ohne sie zu prüfen. Füge `tsc --noEmit` als separaten Job-Schritt hinzu, damit Typfehler einschließlich TS1384 bei jedem Pull Request auffallen.

tsconfig-Änderungen mit dem Diff-Viewer prüfen

Änderungen an der tsconfig.json – etwa `isolatedModules` hinzufügen, `moduleResolution` umstellen oder `lib` aktualisieren – können TS1384 in Dateien einführen, die zuvor sauber kompilierten. Wenn eine tsconfig-Änderung ansteht, nutze den Diff-Viewer, um alte und neue Konfiguration nebeneinander zu vergleichen. So siehst du sofort, welche Optionen sich geändert haben, und kannst neue TS1384-Fehler auf die konkrete Einstellung zurückführen.

Tip

Validiere nach der Behebung von TS1384 die Syntax deiner tsconfig.json mit dem [JSON-Formatierer und -Validator](/tools/data/formatters/json-formatter-viewer) – tsconfig-Dateien sind JSON, und ein nachgestelltes Komma oder ein fehlendes Anführungszeichen verhindert still, dass TypeScript die gerade vorgenommene Konfigurationsänderung liest.

Diff-Viewer

Vergleiche zwei Versionen von tsconfig.json, package.json oder beliebigen Textdateien nebeneinander, um genau zu sehen, was sich geändert hat – im Browser, ohne Upload.

Open tool

Key takeaways

  • TS1384 tritt auf, wenn ein `export`-Modifizierer in einem `declare module`- oder `declare global`-Erweiterungsblock steht – der Fix ist fast immer eine einzige Zeile.
  • Häufigste Ursache: Die Datei hat keine Imports oder Exports, TypeScript behandelt sie also als Skript. Füge oben `export {}` hinzu, um sie in ein Modul umzuwandeln.
  • Mit `isolatedModules: true` (Vite-, Next.js-, esbuild-Projekte) verschiebe Erweiterungen in `.d.ts`-Dateien – sie sind von der Transformation ausgenommen und umgehen die Einschränkung vollständig.
  • Zeigt TS1384 auf einen Pfad in `node_modules`, ist `skipLibCheck: true` in der tsconfig.json der Fix – Deklarationsdateien von Abhängigkeiten kannst du nicht bearbeiten.
  • Ambient-Moduldefinitionen (untypisierte Bibliotheken typisieren) und Modulerweiterungen (typisierte Bibliotheken erweitern) sehen ähnlich aus, verhalten sich aber anders: `export` im Block ist nur in Definitionen gültig, nicht in Erweiterungen.
  • Nimm `tsc --noEmit` in deine CI-Pipeline auf, um TS1384 bei jedem Pull Request zu erkennen, auch wenn dein Bundler (esbuild, SWC) beim Build keine Typprüfung durchführt.
  • Validiere die tsconfig.json-Syntax nach Änderungen mit dem JSON-Formatierer und -Validator – ein JSON-Syntaxfehler verhindert still, dass TypeScript deine Konfiguration liest.

Häufige Fragen

TS1384 bedeutet, dass TypeScript einen `export`-Modifizierer an einer Stelle gefunden hat, an der er nicht erlaubt ist – genauer gesagt innerhalb eines Modulerweiterungs-Blocks. Die vollständige Meldung lautet: „Der Modifizierer 'export' kann nicht auf eine Modulerweiterung angewendet werden." Modulerweiterungen erweitern vorhandene Typen mit `declare module '...' {}` oder `declare global {}`. Sie können keine neuen Symbole exportieren – sie fügen nur Deklarationen zu einem bereits existierenden Modul hinzu. Jedes `export` innerhalb des Erweiterungsblocks löst TS1384 aus.

Der häufigste Fix ist, sicherzustellen, dass die Datei ein Modul und kein Skript ist. Füge `export {}` oben hinzu, wenn die Datei keine weiteren Imports oder Exports enthält. Das wandelt sie vom Skript- in den Modulkontext um, den TypeScript für die Erweiterungssyntax `declare module` und `declare global` verlangt. Wenn du neue Typen hinzufügen und nicht vorhandene erweitern willst, verschiebe die Typdeklarationen aus dem `declare module`-Block heraus.

Der Block `declare global {}` muss in einer Datei stehen, die TypeScript bereits als Modul behandelt – also mindestens einen `import` oder `export` auf oberster Ebene enthält. Ohne das behandelt TypeScript die Datei als Skript, und `declare global` in einer Skriptdatei erzeugt TS1384. Füge am Ende der Datei `export {}` hinzu, um den Modulmodus zu erzwingen, ohne tatsächlich etwas zu exportieren. Das ist das Standardmuster für Dateien mit globalen Typ-Erweiterungen.

Eine TypeScript-Datei ist ein Skript, wenn sie keine `import`- oder `export`-Anweisungen auf oberster Ebene enthält – Deklarationen in Skripten teilen sich einen globalen Gültigkeitsbereich, der für alle anderen Skriptdateien sichtbar ist. Eine Datei mit mindestens einem `import` oder `export` ist ein Modul mit eigenem, isoliertem Gültigkeitsbereich. Die Syntax für Modulerweiterungen ist nur in Moduldateien erlaubt. Ein `export {}` – ein leerer Export – macht aus einem Skript ein Modul und behebt TS1384, ohne das Laufzeitverhalten zu ändern.

Ja, in bestimmten Szenarien. Mit `isolatedModules: true` in der tsconfig.json verlangt TypeScript, dass jede Datei unabhängig transformierbar ist. Reine Typ-Erweiterungen in regulären .ts-Dateien können TS1384 auslösen, wenn esbuild oder Babel sie verarbeiten wollen, weil diese Werkzeuge dateiübergreifende Typinformationen nicht auflösen können. Das Verschieben der Erweiterung in eine .d.ts-Datei behebt das – Deklarationsdateien werden von allen großen Bundlern von der Transformation ausgenommen.

Ja. Wenn ein Paket fehlerhafte Typdeklarationen mit `export` innerhalb eines Modulerweiterungs-Blocks ausliefert, erzeugt dein Projekt TS1384, sobald TypeScript diese Deklarationen liest. Der pragmatische Fix ist `skipLibCheck: true` in der tsconfig.json, wodurch die Typprüfung der Deklarationsdateien in node_modules übersprungen wird. Das ist ein Workaround – die richtige Lösung ist, dass der Paketautor die Deklarationen korrigiert. Erwäge, ein Issue im Paket-Repository mit dem konkreten TS1384-Kontext zu eröffnen.

TS2669 („Erweiterungen des globalen Gültigkeitsbereichs können nur direkt in externen Modulen oder Ambient-Moduldeklarationen verschachtelt werden") steht in engem Zusammenhang. Beide Fehler treten auf, wenn der Dateikontext für eine Modulerweiterung falsch ist. TS1384 wird ausgelöst, wenn ein `export`-Modifizierer im Erweiterungsblock selbst steht; TS2669 wird ausgelöst, wenn ein `declare global {}`-Block in einer Skriptdatei statt in einem Modul steht. Der Fix ist bei beiden identisch: Füge mindestens eine `import`- oder `export`-Anweisung zur Datei hinzu.

Führe `tsc --noEmit` im Projektstamm aus – TypeScript validiert die tsconfig.json und meldet Konfigurationsfehler, ohne Ausgabedateien zu erzeugen. Bei JSON-Syntaxfehlern in der tsconfig.json selbst (fehlende Kommas, nachgestellte Kommas, falsche Eigenschaftsnamen) füge den Dateiinhalt in den JSON-Formatierer und -Validator von Aback Tools ein, der Syntaxprobleme sofort im Browser hervorhebt – ganz ohne installierten TypeScript-Compiler.

ShareXLinkedIn