2016-12-01 31 views
17

有一个简单的TS包,用作CommonJS模块并且没有导出。 TS文件被编译成具有相同名称的JS文件并用作require('package/option-foo')'无法在不相关的文件中重新声明块范围变量'

tsconfig.json:

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

期权foo.ts:

declare const GlobalVar: any; 

function baz() {} 

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

期权bar.ts:

declare const GlobalVar: any; 

function baz() {} 

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

这里最重要的部分是option-foooption-bar从未一起使用。该项目中还有其他免费的TS文件,但它们不影响任何内容,只需要在一个tsc运行中被转换为JS。

tsc运行时,它抛出

不能重新声明块作用域变量 'GlobalVar'。

重复函数的实现。

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

重复函数的实现。

for GlobalVar and baz in both files。

如何处理这些问题而不会使构建过程或这两个TS文件的输出复杂化?

+0

在这个特定的情况下,你可以像'custom-typings.d.ts'文件那样声明它,如果它们都是'any'。您也可以尝试更改所需的'--module'编译(尝试AMD/System,因为我相信它们可以单独对文件进行范围)。 – Seiyria

回答

32

TL; DR只写export {}在文件的最外层。


在某些时候需要有一个文件是否应被视为一个模块语义歧义(并且有它自己的范围内)或脚本(并与其他脚本全局范围)。

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

但是使用JavaScript的其他地方呢?不幸的是,现在还没有一个标准的方式来作出这种区分。

TypeScript决定解决这个问题的方式是简单说明一个模块是任何包含导入或导出文件的文件。

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

要解决这个问题,你可以简单地有一个export语句,它不输出任何内容。换句话说,只需编写

export {}; 

某处在您的文件的顶层。

+0

第二个想法,我结束了这个解决方案,它只是工作。谢谢。 – estus

+0

这是对这个问题的最好解释。这个问题困扰了我很长一段时间。今天,我终于找到原因。 – novaline

+0

所以它是抱怨的TS编译器,而不是运行时问题,烦人。有没有办法忽略这样的TS错误? –

8

GlobalVar和函数暴露于全局空间,并且typescript警告您该变量和方法名称将被重新声明。因为这两个函数是在全局名称空间中声明的,所以你只需要声明一次。 如果你想这样做。使用命名空间

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

} 

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

您可以通过使用bar.baz前的命名空间的名称调用该函数在C#,foo.baz

希望这有助于你