Visual Studio 2017 中的 TypeScript:自动定义包含导致重复标识符错误

TypeScript in Visual Studio 2017: Automatic definition inclusion causes Duplicate Identifier errors

更新: 我有一个解决方法,可以让事情在没有黑客的情况下正常工作。我将下面描述的先前尝试留给后代。查看工作解决方案的答案。


我刚刚将一个项目升级到 Visual Studio 2017,我突然遇到了各种 TypeScript 错误。其中许多是 Duplicate identifier 错误。当我双击其中一个错误时,它会打开一个名为 index.d.ts 的文件,该文件位于以下目录中:

C:\Users\[me]\AppData\Local\Microsoft\TypeScript\node_modules\@types\jquery\index.d.ts

根据我在此页面上阅读的内容:

https://blogs.msdn.microsoft.com/visualstudio/2016/11/28/more-productive-javascript-in-visual-studio-2017-rc/

...似乎正在发生的事情是 Visual Studio 正在尝试为我已经手动包含定义文件的类型下载定义文件。自动包含定义文件听起来是个很棒的功能!我会删除手动包含的,对吗?但我所做的一切似乎都不起作用。我希望有人能告诉我哪里错了。

作为背景,我在 Visual Studio 2015 年的工作方式如下。我使用了三个库:jQuery、jQuery UI 和 QUnit。我只是从 DefinitelyTyped 下载了 .d.ts 文件,并将它们放在我项目的 Scripts 目录中,一切正常,直到我在 VS 2017 中打开项目。

从错误消息来看,似乎 Visual Studio 2017 引入了自己的定义文件,所以我想我只需删除我手动引入的那些。但是,当我这样做时,现在出现大量 Cannot find name $ 错误,这似乎意味着由于某种原因不再引入这些定义文件。

接下来,我认为问题可能出在我的项目中实际上没有 JQuery(和其他库)源文件。我只是在我的 HTML 源中从 Google 的 CDN 引用它们。上面的 link 听起来像是 Visual Studio 正在寻找一个实际的松散文件作为它应该引入定义文件的指示符。所以我手动将文件添加到我的脚本目录并重建,但没有任何改变。

上面的 linked 页面还讨论了从 npm 或 bower 中包含你的库文件,或者使用 tsconfig.json 文件,但在我走那些路之前(不是我正常工作流程的一部分) ),我希望有人能告诉我,在 Visual Studio 2017 中是否有引入 TypeScript 定义的首选方法?提前致谢。


更新:(也请参阅下面的更新 2)我能够让事情正常进行。这不是很直观,所以我在这里分享我的步骤,希望 a) 它能帮助别人,b) 如果我只是做错了,有人可以告诉我。

  1. 从项目中删除所有 TypeScript 代码和定义文件。
  2. 打开 packages.json 并删除其中的任何定义文件引用。
  3. 清理并构建。没有错误或警告。
  4. 通过NuGet,安装你需要的定义文件(例如jQuery,你想要的包是"jquery.TypeScript.DefinitelyTyped")。
  5. 这将在 Scripts\typings\jquery 中安装定义文件。
  6. 对您引用的其他库执行相同的操作。
  7. 添加一个新的测试 TypeScript 文件并添加一行尝试使用库,例如​​ var foo = $(document);
  8. 智能感知有效!项目建立!看来我们又回来了!
  9. 没那么快。几秒钟后,我们再次收到重复标识符错误。似乎 Visual Studio 自己获取了定义文件(可能是我通过 NuGet 包含定义文件激活的)现在我们又发生了冲突。
  10. 使用以下指令添加 tsconfig.js 文件,以防止 Visual Studio 下载其自己的定义文件副本:{ "compilerOptions": { "types": [] } }
  11. 错误消失。
  12. 没那么快!几秒钟后,出现了数百个新错误,引用了我已从项目中完全删除的 TypeScript 文件。打开错误 window 中引用的文件之一,似乎在 <Project>\obj\Debug\... 中进行了复制(路径较长但我忘记记录了)
  13. 解决方案再多的清理也无法删除这些文件。
  14. 手动删除整个 obj 目录。
  15. 将我所有的原始 TypeScript 文件添加回项目中。
  16. 重建。成功!

更新 2: 我发现上述方法存在一些缺点。我也有更好的解决办法。

使用tsconfig.json 有一个很大的缺点。保存时重新编译的选项在 Visual Studio 中不起作用。我想让我的站点 运行 处于调试模式,对 TypeScript 进行一些更改,点击保存,然后立即在站点中看到这些更改。

我认为给我带来麻烦的一件事是我的 TypeScript 文件位于 Scripts 以外的文件夹中, 我为应该部署的文件保留了这些文件按原样发送到服务器。我猜微软认为这是一个非标准用例。

在为此苦思冥想了太久之后,我找到了一个简单但老套的解决方案。我把这个目录下的所有子目录都拿走了:

C:\Users\[me]\AppData\Local\Microsoft\TypeScript\node_modules\@types

并将它们移动到一个名为 Deleted 的目录中。

砰。不再自动包含定义,不再出现错误。

Microsoft,如果您正在阅读,请为我的方案提供支持,重申一下:


更新 3: 我终于让它工作了。请参阅下面的答案以获得非 hacky 解决方案。

我在更新到 VS 2017 的旧应用程序中遇到了这个确切的问题,并按照 harley.333 的回答修复了它 - 修改安装以包含 TypeScript 2.0 SDK。

我没有代表发表评论,但要找到它,您必须将标签翻到 "Individual Components",然后它在最后一个分组中,"SDKs, libraries and frameworks."

Install Typescript SDK Screenshot

我没有任何技巧就让它工作了。 诀窍是使用 tsconfig.json 文件并禁用自动定义包含。在我最初的问题中,我提到我尝试过这个并发现我无法使用保存时编译。但是,那是因为我试图使用 "watch" 选项,而我确实应该使用 "compileOnSave" 选项。

这是我的一套完整的工作步骤,用于将我原来的、损坏的项目转换为正常工作的项目并且将在 Visual Studio 2017[=51= 的未修改安装中继续正常工作].

tsconfig.json 文件添加到项目的根目录。

配置您的文件至少:

{ "compilerOptions": { "types": [] } }

但也许还有您喜欢的其他选项。我的文件如下所示:

{
  "compileOnSave": true,
  "compilerOptions": {
    "types": [],
    "sourceMap": true,
    "target": "es5",
    "noEmitOnError": true
  }
}

您可以在此处了解其他编译器选项: https://www.typescriptlang.org/docs/handbook/compiler-options.html

阻止自动包含定义的是 "types":[] 部分。

这意味着您可以自行决定为您使用的任何库引入定义。幸运的是,通过 NuGet 非常容易。例如,对于 jQuery,只需搜索 jquery.TypeScript.DefinitelyTyped 并安装相应的版本。这将在 Scripts/typings 下创建文件夹。

如果您之前有错误,您可能需要清除一些错误信息。清理您的项目,删除项目目录结构顶部的 obj 目录,它现在应该可以正确构建。当我在文件中输入一些内容然后再次保存时,我有几个杂散错误消失了。也可能需要重新启动 Visual Studio。

祝你好运!


更新: 我发现当我发布到 Azure 时,我又遇到了错误。但是,当我将下面 Perfa 建议的指令添加到我的 tsconfig.json 文件,删除我的 bin 和 obj 目录并重新启动 Visual Studio 时,这些错误也不再出现.我现在已经多次构建和重建并发布到 Azure,它们看起来很好而且真的消失了。

为清楚起见,我的完整 tsconfig.json 文件现在如下所示:

{
  "compileOnSave": true,
  "compilerOptions": {
    "types": [],
    "sourceMap": true,
    "target": "es5",
    "noEmitOnError": true
  },
  "exclude": [
    "node_modules",
    "obj",
    "bin"
  ]
}

安装 VS 2017 后出现此错误。为了摆脱它,我用 obj 和 bin 更新了我的 tsconfig.json exclude 部分。

"exclude": [
    "node_modules",
    "obj",
    "bin"
  ]