71 votes

'Cannot redeclare block-scoped variable' dans des fichiers non liés

Il existe un package TS simple qui est utilisé en tant que modules CommonJS et n'a pas d'exports. Les fichiers TS sont compilés en fichiers JS portant le même nom et sont utilisés avec require('package/option-foo').

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5"
  }
}

option-foo.ts:

declare const GlobalVar: any;

function baz() {}

if (GlobalVar.foo) GlobalVar.baz = baz;

option-bar.ts:

declare const GlobalVar: any;

function baz() {}

if (GlobalVar.bar) GlobalVar.baz = baz;

L'élément important ici est que option-foo et option-bar ne sont jamais utilisés ensemble. Il existe d'autres fichiers TS complémentaires dans le projet, mais ils n'affectent rien, ils doivent juste être transpilés en JS dans une seule exécution de tsc.

Lorsque tsc s'exécute, il lance

Impossible de redéclarer la variable de bloc à portée 'GlobalVar'.

Implémentation de fonction en double.

Impossible de redéclarer la variable de bloc à portée 'GlobalVar'.

Implémentation de fonction en double.

pour GlobalVar et baz dans les deux fichiers.

Comment cela peut-il être traité sans compliquer le processus de construction ou la sortie de ces deux fichiers TS ?

1 votes

Dans ce cas spécifique, vous pouvez avoir quelque chose comme un fichier custom-typings.d.ts et simplement le déclarer là-bas, s'ils sont tous les deux any. Vous pourriez également essayer de changer la compilation --module souhaitée (essayer AMD/System, car je crois qu'ils scindent les fichiers individuellement).

182voto

Daniel Rosenwasser Points 7171

TL;DR Il suffit d'écrire export {} dans la portée la plus extérieure de vos fichiers.


À un moment donné, il doit y avoir une désambiguïsation sémantique pour savoir si un fichier doit être traité comme un module (et avoir sa propre portée) ou un script (et partager la portée globale avec d'autres scripts).

Dans le navigateur, c'est facile - vous devriez pouvoir utiliser une balise </code> et vous pourrez utiliser des modules.</p> <p>Mais que se passe-t-il pour tout autre endroit utilisant JavaScript? Malheureusement, il n'existe pas actuellement de moyen standard pour faire cette distinction.</p> <p>La manière dont TypeScript a décidé de s'attaquer au problème a été simplement de déclarer qu'un module est <em>tout fichier contenant une instruction d'import ou d'export</em>.</p> <p>Donc si votre fichier ne contient aucune sorte d'instructions <code>import</code> ou <code>export</code> au niveau supérieur, vous verrez parfois des problèmes d'interférences avec les déclarations globales se produire.</p> <p>Pour contourner cela, vous pouvez simplement avoir une instruction <code>export</code> qui n'exporte rien. En d'autres termes, il suffit d'écrire</p> <pre><code>export {}; </code></pre> <p>quelque part au niveau supérieur de votre fichier.</p></x-turndown>

0 votes

Sur la deuxième pensée, j'ai abouti à cette solution, ça fonctionne juste. Merci.

3 votes

C'est la meilleure explication à ce problème. Ce problème m'a longtemps posé confusion. Aujourd'hui, j'ai enfin trouvé la raison.

0 votes

C'est donc le compilateur TS qui se plaint, ce n'est pas un problème d'exécution, ennuyeux. Y a-t-il un moyen d'ignorer les erreurs TS comme celle-ci?

20voto

freedeveloper Points 2087

GlobalVar et les fonctions sont exposés à l'espace de noms global, et TypeScript vous avertit que la variable et le nom de la méthode sont redéclarés. Étant donné que les deux fonctions sont déclarées dans l'espace de noms global, vous n'avez besoin de les déclarer qu'une seule fois.

Si vous voulez faire cela, utilisez des espaces de noms.

namespace foo {    
    declare const GlobalVar: any;
    function baz() {}
}

namespace bar {
    declare const GlobalVar: any;
    function baz() {}
}

Vous pouvez appeler les fonctions de la même manière que vous les appelez en C#, en utilisant le nom de l'espace de noms : bar.baz ou foo.baz.

9voto

lance.dolan Points 882

À partir de TypeScript 4.7, cela est résolu via "moduleDetection": "force" dans votre tsconfig.json :

{
  "compilerOptions": {
    // ... Diverses options ici, telles que module ...
    "moduleDetection": "force"
  }
}   

Référence: https://www.typescriptlang.org/tsconfig#moduleDetection

Problème Github original qui a motivé cette configuration : https://github.com/microsoft/TypeScript/issues/14279

0 votes

Merci. Je suppose que c'est la solution préférable maintenant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X