web-dev-qa-db-fra.com

'Impossible de redéclarer une variable à portée de bloc' dans des fichiers indépendants

Il existe un package TS simple utilisé en tant que modules CommonJS et n’a aucune exportation. Les fichiers TS sont compilés en fichiers JS portant le même nom et utilisés en tant que 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;

La partie importante ici est que option-foo et option-bar sont jamais utilisés ensemble. Il y a d'autres fichiers TS complémentaires dans le projet, mais ils n'affectent en rien, ils doivent simplement être transpilés au format JS en une seule exécution tsc.

Quand tsc s'exécute, il jette

Impossible de redéclarer la variable étendue du bloc 'GlobalVar'.

Dupliquer la mise en oeuvre.

Impossible de redéclarer la variable étendue du bloc 'GlobalVar'.

Dupliquer la mise en oeuvre.

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?

50
Estus Flask

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


Une ambiguïté sémantique est nécessaire à un moment donné pour déterminer si un fichier doit être traité comme un module (et avoir sa propre portée) ou comme un script (et partagez l'étendue globale avec d'autres scripts).

Dans le navigateur, cela est facile - vous devriez pouvoir utiliser un <script type="module"> tag et vous pourrez utiliser des modules.

Mais qu'en est-il de tout autre endroit qui utilise JavaScript? Malheureusement, il n'y a pas de moyen standard pour faire cette distinction.

Pour résoudre ce problème, TypeScript a simplement décidé qu'un module est tout fichier contenant une importation ou une exportation .

Ainsi, si votre fichier ne contient aucune sorte d'instructions import ou export de niveau supérieur, vous verrez parfois des problèmes d'interférence entre les déclarations globales.

Pour contourner cela, vous pouvez simplement avoir une instruction export qui n'exporte rien. En d'autres termes, il suffit d'écrire

export {};

quelque part au plus haut niveau de votre fichier.

119
Daniel Rosenwasser

GlobalVar et les fonctions sont exposées à l'espace de noms global, et TypeScript vous avertit que la variable et le nom de la méthode sont à nouveau déclarés. Les deux fonctions étant déclarées dans l'espace de noms global, il vous suffit de les déclarer une 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 qu'en C #, en utilisant le nom de l'espace de nom: bar.baz ou foo.baz.

18
freedeveloper