'无法在不相关的文件中重新声明块范围变量'

Est*_*ask 52 typescript tsc

有一个简单的TS包用作CommonJS模块,没有导出.TS文件被编译为具有相同名称的JS文件并用作require('package/option-foo').

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5"
  }
}
Run Code Online (Sandbox Code Playgroud)

期权foo.ts:

declare const GlobalVar: any;

function baz() {}

if (GlobalVar.foo) GlobalVar.baz = baz;
Run Code Online (Sandbox Code Playgroud)

期权bar.ts:

declare const GlobalVar: any;

function baz() {}

if (GlobalVar.bar) GlobalVar.baz = baz;
Run Code Online (Sandbox Code Playgroud)

这里最重要的部分是option-foooption-bar从来没有一起使用.项目中还有其他免费的TS文件,但它们不会影响任何东西,只需要在一次tsc运行中转换为JS .

tsc运行时,它抛出

无法重新声明块范围变量'GlobalVar'.

重复的功能实现.

无法重新声明块范围变量'GlobalVar'.

重复的功能实现.

for GlobalVarbazin两个文件.

如何在不使构建过程或这两个TS文件的输出复杂化的情况下进行处理?

Dan*_*ser 127

TL; DR只需写入export {}文件的最外层.


在某些时候,需要对文件是否应被视为模块(并具有自己的范围)或脚本(并与其他脚本共享全局范围)进行语义消歧.

在浏览器中,这很容易 - 您应该能够使用<script type="module">标签,并且您将能够使用模块.

但是利用JavaScript的其他任何地方呢?不幸的是,目前还没有一种标准方法可以做出这种区分.

TypeScript决定解决问题的方法是简单地声明模块是包含导入或导出的任何文件.

因此,如果您的文件没有任何类型的顶级importexport语句,那么您偶尔会看到全局声明相互干扰的问题.

为了解决这个问题,您可以简单地使用一个export不导出任何内容的语句.换句话说,就是写

export {};
Run Code Online (Sandbox Code Playgroud)

位于文件顶层的某个地方.

  • 这是对这个问题最好的解释。这个问题让我困惑了很长时间。今天终于找到原因了。 (3认同)
  • 它会一直工作,直到出现 SyntaxError: Unexpected token export 为止。我希望他们能够接受这是 NodeJS 打字稿中的一个错误,并为其开发修复程序。 (3认同)
  • 虽然我很欣赏这个黑客,但添加这个是一种味道。为什么 TS 将进口视为重新申报?模块是有范围的。TS真的应该修复这个bug.. (2认同)

lan*_*lan 25

从 TypeScript 4.7 开始,这个问题可以通过"moduleDetection": "force"tsconfig.json 解决:

{
  "compilerOptions": {
    // ... Various options here, such as module ...
    "moduleDetection": "force"
  }
}   

Run Code Online (Sandbox Code Playgroud)

参考: https: //www.typescriptlang.org/tsconfig#moduleDetection

驱动此配置的原始 Github 问题:https ://github.com/microsoft/TypeScript/issues/14279


fre*_*per 19

GlobalVar并且函数暴露给全局命名空间,TypeScript警告您重新声明变量和方法名称.因为这两个函数是在全局命名空间中声明的,所以您只需要声明它们一次.

如果要执行此操作,请使用名称空间.

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

namespace bar {
    declare const GlobalVar: any;
    function baz() {}
}
Run Code Online (Sandbox Code Playgroud)

您可以使用命名空间名称:bar.baz或者以与在C#中调用它们相同的方式调用这些函数foo.baz.