L'erreur TypeScript TS1384 fait partie de ces erreurs qui semblent cryptiques à première vue mais dont la cause est toujours précise et corrigeable. Elle apparaît lorsque le compilateur trouve un modificateur export à un endroit où il ne peut pas légalement figurer, précisément dans un bloc d'augmentation de module. Ce guide explique exactement ce que signifie TS1384, passe en revue chaque scénario qui le déclenche et donne le bon correctif pour chacun.
Qu'est-ce que TS1384 ?
L'erreur TypeScript TS1384 porte le message : « le modificateur "export" ne peut pas s'appliquer à une augmentation de module ». Elle apparaît lorsque le compilateur rencontre un mot-clé `export` dans un bloc `declare module` ou `declare global`, les deux constructions que TypeScript utilise pour l'augmentation de module. Les blocs d'augmentation servent à étendre les types de modules existants, pas à déclarer de nouveaux symboles publics : `export` y est donc structurellement invalide.
L'augmentation de module en une phrase
L'augmentation de module est le mécanisme TypeScript qui permet d'ajouter des membres aux types d'un module existant : par exemple ajouter une propriété personnalisée à `Express.Request`, étendre `Window` avec un global tiers ou ajouter des méthodes aux options de composants d'un framework. La syntaxe ressemble à un bloc `declare module 'nom-du-module' {}` et doit se trouver dans un fichier de module (un fichier comportant au moins une instruction `import` ou `export` de premier niveau).
- TS1384 est une erreur du compilateur : le fichier ne passera pas la vérification de type tant qu'elle n'est pas corrigée
- Elle n'affecte pas l'exécution : l'erreur ne concerne que les déclarations de type
- Elle est déterministe : le même code la déclenche toujours, il n'existe pas de version intermittente
- Ses causes racines sont peu nombreuses : contexte script contre module, isolatedModules et structure .d.ts incorrecte couvrent 95 % des cas
Note
Quand TS1384 se déclenche
L'erreur implique toujours un `export` là où TypeScript ne l'autorise pas. Trois motifs distincts la produisent, et déterminer lequel s'applique à votre base de code détermine le bon correctif.
Motif 1 : export dans un bloc declare module
Le déclencheur le plus direct : vous écrivez une instruction `export` dans une augmentation `declare module`. L'intention est généralement d'ajouter quelque chose à l'API publique du module, mais les blocs d'augmentation ne fonctionnent pas ainsi : ils ne peuvent qu'étendre des déclarations de type déjà présentes dans le module cible.
// ✗ TS1384 - export dans une augmentation de module
declare module 'some-library' {
export interface NewInterface { // <-- TS1384 se déclenche ici
id: string;
}
}
// ✓ Correct - interface ajoutée sans export
declare module 'some-library' {
interface ExistingInterface {
newProperty: string; // étend le type existant
}
}Motif 2 : le fichier est traité comme un script, pas un module
C'est la cause la plus fréquente de TS1384 dans les vrais projets. Si un fichier ne contient aucune instruction `import` ou `export` de premier niveau, TypeScript le traite comme un script à portée globale. Un bloc `declare global {}` dans un fichier de script n'a pas de sens (les globales sont déjà globales dans un script), donc TypeScript rejette tout `export` qu'il contient avec TS1384. Le fichier doit être un module pour que le contexte d'augmentation ait un sens.
Motif 3 : structure incorrecte du fichier .d.ts
Les fichiers de déclaration (`.d.ts`) qui mélangent déclarations de module ambiant et instructions `export` classiques dans le mauvais ordre peuvent déclencher TS1384. Un `.d.ts` qui commence par des déclarations `export` de premier niveau puis contient un bloc `declare module` est traité comme un module, ce qui est correct. Mais un `.d.ts` qui englobe tout dans un unique bloc `declare module` puis tente d'utiliser `export` dans ce bloc confond le contexte d'augmentation avec un contexte de définition de module.
Warning
Corriger TS1384 : augmentation de module
Le bon correctif dépend de ce que vous cherchez réellement à accomplir. Deux objectifs différents peuvent mener à TS1384 et demandent des approches différentes. Suivez ces quatre étapes pour résoudre l'erreur proprement.
Identifier le motif qui déclenche TS1384
Lisez attentivement l'erreur complète du compilateur. Notez l'extension du fichier (.ts ou .d.ts), le numéro de ligne et si l'`export` se trouve dans un bloc `declare module`, un bloc `declare global` ou ailleurs. Le contexte du code environnant vous indiquera lequel des trois motifs ci-dessus s'applique. Si le chemin de l'erreur commence par `node_modules/`, passez au correctif `skipLibCheck` : les autres motifs ne s'appliquent pas.
Ajouter export {} pour convertir le fichier en module
Si votre fichier contient un bloc `declare module` ou `declare global` mais aucun import ou export de premier niveau, ajoutez `export {}` en haut. Cette seule ligne fait passer le fichier d'un contexte de script à un contexte de module, l'environnement requis pour la syntaxe d'augmentation. L'export vide n'ajoute rien au résultat compilé : c'est purement un signal de contexte pour TypeScript.
// Ajoutez cette ligne pour convertir le fichier en module
export {};
declare global {
interface Window {
myAnalytics: AnalyticsInstance;
}
}Déplacer declare global dans un module existant
Une alternative à l'ajout de `export {}` consiste à placer le bloc `declare global` dans un fichier comportant déjà de vrais imports ou exports, comme le point d'entrée d'une bibliothèque, un module de fonctionnalité ou un fichier d'utilitaires partagés. Cette approche garde vos augmentations de type à côté du code qu'elles étendent, ce qui peut être plus facile à maintenir qu'un fichier de déclarations globales dédié.
Supprimer export à l'intérieur du bloc d'augmentation
Si vous voulez réellement ajouter un nouveau type exportable à l'API publique d'un module existant, le bloc d'augmentation n'est pas le bon endroit. Déplacez la déclaration entièrement en dehors du bloc `declare module`. Pour augmenter une interface existante, utilisez le même nom d'interface sans `export` dans le bloc : TypeScript la fusionne automatiquement via la fusion de déclarations.
Formateur et validateur JSON
Validez votre tsconfig.json et votre package.json pour détecter les erreurs de syntaxe instantanément dans votre navigateur, sans compilateur TypeScript.
TS1384 et isolatedModules
L'option de compilateur `isolatedModules` est activée par défaut dans Vite, Next.js, Create React App avec Babel et tout projet utilisant esbuild ou SWC. Elle exige que chaque fichier soit transformable indépendamment, sans information de type inter-fichiers, ce qui ajoute des contraintes qui amplifient plusieurs erreurs TypeScript, dont TS1384.
Ce que restreint isolatedModules
| Construction | Sans isolatedModules | Avec isolatedModules |
|---|---|---|
| `const enum` | ✓ Autorisé partout | ✗ Uniquement dans les .d.ts |
| `export type` | ✓ Facultatif | ✓ Obligatoire pour réexporter des types |
| `import type` | ✓ Facultatif | ✓ Obligatoire pour importer des types |
| Déclarations ambiantes | ✓ Dans tout fichier .ts | ✓ Préférable dans un .d.ts |
| Augmentation de module | ✓ Dans un .ts module | ✓ Préférable dans un .d.ts |
| Réexport d'espaces de noms | ✓ Autorisé | ✗ Restreint |
Le correctif propre à isolatedModules
Quand `isolatedModules` est actif et que TS1384 apparaît sur une augmentation dans un fichier `.ts` classique, le correctif le plus propre est de déplacer l'augmentation dans un fichier `.d.ts`. Les fichiers de déclaration ne sont jamais transformés par esbuild ou Babel : seul le compilateur TypeScript les lit. Cela élimine complètement la contrainte isolatedModules pour cette augmentation.
// Ce motif fonctionne correctement avec isolatedModules
export {};
declare module 'express' {
interface Request {
userId?: string;
tenantId?: string;
}
}Tip
TS1384 dans les fichiers .d.ts
Les fichiers de déclaration ajoutent leurs propres nuances à TS1384. Les règles sur ce qui est valide dans un fichier `.d.ts` diffèrent légèrement de celles des fichiers `.ts` classiques, et les motifs qui produisent TS1384 dans les fichiers de déclaration sont souvent moins intuitifs.
Définition de module ambiant ou augmentation ?
Un fichier `.d.ts` peut contenir deux choses fondamentalement différentes qui se ressemblent mais se comportent autrement. Une définition de module ambiant (`declare module 'nom' {}` dans un `.d.ts` en contexte de script, sans import ni export) définit de zéro tous les types d'un module : elle sert à typer des bibliothèques JavaScript non typées. Une augmentation de module (`declare module 'nom' {}` dans un `.d.ts` en contexte de module avec un `export {}`) étend les types d'un module existant. La distinction est importante car `export` est valide dans une définition de module ambiant mais produit TS1384 dans une augmentation de module.
Choisir le bon motif .d.ts
Si votre fichier `.d.ts` définit les types d'une bibliothèque non typée (par exemple typer un ancien plugin jQuery), gardez-le en contexte de script sans `export {}` en tête. Utilisez `export` librement dans le bloc `declare module`. Si votre fichier `.d.ts` augmente une bibliothèque déjà typée (par exemple ajouter une propriété à `Express.Request`), ajoutez `export {}` en haut et retirez tout `export` du bloc `declare module`.
Note
skipLibCheck en dernier recours
Quand TS1384 apparaît sur un chemin dans `node_modules` et que vous n'avez aucun contrôle sur le paquet, ajoutez `"skipLibCheck": true` à votre tsconfig.json. Cela indique à TypeScript d'ignorer la vérification de type de tous les fichiers `.d.ts`, y compris ceux de `node_modules`. C'est une option de configuration légitime et très répandue, pas un bricolage. La contrepartie est que vous perdez entièrement la vérification de type des déclarations de bibliothèques : des types réellement défectueux dans les dépendances passeront inaperçus. N'utilisez `skipLibCheck` que lorsque l'alternative est de bloquer votre build.
TS1384 dans les frameworks et bundlers
Chaque framework et outil de build configure TypeScript différemment, ce qui signifie que TS1384 peut apparaître pour des raisons légèrement différentes selon votre stack. Voici comment les environnements les plus courants produisent et résolvent l'erreur.
Next.js
Next.js active `isolatedModules` automatiquement via son tsconfig par défaut et utilise SWC pour la transformation. Le motif standard d'augmentation de types dans Next.js est un répertoire `types/` dédié à la racine du projet, contenant des fichiers `.d.ts` commençant par `export {}`. Next.js génère aussi un fichier `next-env.d.ts` : ne l'éditez jamais à la main, car il est régénéré à chaque build et vos modifications seront perdues. Ajoutez vos augmentations dans un fichier séparé.
Vite
Les projets Vite utilisent esbuild pour la transformation et incluent `isolatedModules: true` dans le tsconfig par défaut. Vite génère également un fichier `vite-env.d.ts` pour ses propres globales. Ajoutez les augmentations de module dans un répertoire `src/types/` séparé. Le motif `export {}` résout TS1384 dans toutes les configurations Vite standard, et conserver les augmentations dans des fichiers `.d.ts` reste l'approche la plus sûre lorsque la transformation esbuild est dans la chaîne.
API Node.js / Express simples
Les projets Express augmentent souvent `Express.Request` pour ajouter la session utilisateur ou le contexte d'authentification. Le motif canonique est un fichier `src/types/express/index.d.ts` commençant par `export {}` suivi de l'augmentation `declare module 'express-serve-static-core'`. Sans `isolatedModules`, cela fonctionne aussi dans un fichier `.ts` classique, mais utiliser `.d.ts` reste la convention la plus propre dans tous les cas. Vérifiez toujours le nom exact du module dans les définitions de type d'Express : la cible de l'augmentation est `express-serve-static-core`, pas `express`.
Le fichier doit être un module avant de pouvoir en augmenter un. Un seul `export {}` transforme un script en module et débloque tout le système d'augmentation.
Éviter TS1384 sur le long terme
TS1384 s'introduit facilement par accident, surtout quand de nouveaux membres de l'équipe ajoutent des augmentations de type ou quand vous migrez un projet vers un nouveau bundler. Ces pratiques l'empêchent de revenir après l'avoir corrigé.
Établir une convention de répertoire de types
Créez un répertoire `src/types/` (ou `types/`) et conservez-y toutes les augmentations de module sous forme de fichiers `.d.ts`. Chaque fichier doit contenir une augmentation et commencer par `export {}`. Documentez cette convention dans le `CONTRIBUTING.md` du projet pour que les nouveaux contributeurs sachent où placer les déclarations de type. Un emplacement cohérent facilite aussi l'audit des augmentations lors des mises à jour de dépendances.
Utiliser tsc --noEmit en CI
Exécuter `tsc --noEmit` comme étape de CI détecte TS1384 (et toute autre erreur TypeScript) avant que le code n'atteigne main. Beaucoup de projets sautent la vérification de type en CI parce que leur bundler ne l'exige pas : esbuild et SWC suppriment les types sans les vérifier. Ajoutez `tsc --noEmit` comme étape distincte pour que les erreurs de type, dont TS1384, soient détectées à chaque pull request.
Auditer les changements de tsconfig avec le comparateur de différences
Les modifications de tsconfig.json (ajout de `isolatedModules`, changement de `moduleResolution`, mise à jour de `lib`) peuvent introduire TS1384 dans des fichiers qui compilaient auparavant sans erreur. Quand un changement de tsconfig arrive, utilisez le Comparateur de différences pour comparer l'ancienne et la nouvelle configuration côte à côte. Vous voyez immédiatement quelles options ont changé et pouvez relier les nouveaux TS1384 au réglage précis qui les a causés.
Tip
Comparateur de différences
Comparez deux versions de tsconfig.json, package.json ou de tout fichier texte côte à côte pour voir exactement ce qui a changé, dans le navigateur et sans rien téléverser.
Key takeaways
- TS1384 apparaît quand un modificateur `export` se trouve dans un bloc d'augmentation `declare module` ou `declare global` ; le correctif tient presque toujours en une ligne.
- Cause la plus fréquente : le fichier n'a ni import ni export, TypeScript le traite donc comme un script. Ajoutez `export {}` en tête pour le convertir en module.
- Avec `isolatedModules: true` (projets Vite, Next.js, esbuild), déplacez les augmentations dans des fichiers `.d.ts` : exclus de la transformation, ils évitent complètement la contrainte.
- Si TS1384 pointe vers un chemin dans `node_modules`, le correctif est `skipLibCheck: true` dans tsconfig.json : vous ne pouvez pas modifier les déclarations d'une dépendance.
- Définitions de module ambiant (typer une bibliothèque non typée) et augmentations de module (étendre une bibliothèque typée) se ressemblent mais diffèrent : `export` dans le bloc n'est valide que dans les définitions, pas dans les augmentations.
- Ajoutez `tsc --noEmit` à votre pipeline CI pour détecter TS1384 à chaque pull request, même si votre bundler (esbuild, SWC) ne vérifie pas les types pendant le build.
- Validez la syntaxe de tsconfig.json avec le Formateur et validateur JSON après chaque changement : une erreur de syntaxe JSON empêche silencieusement TypeScript de lire votre configuration.