【问题标题】:Install multiple typescript type definitions declaring the same global variable安装多个 typescript 类型定义,声明相同的全局变量
【发布时间】:2018-08-19 17:31:53
【问题描述】:

我正在使用 typescript、node 和 electron 构建一个应用程序。

我在应用程序中使用 jquery,并且我已经安装了 @types/jquery 包以获得智能提示。

接下来我使用 mocha 和 spectron 创建了一个测试。 Spectron 使用 webdriverio 并通过一些属性公开其 API。我需要使用这些属性,所以我安装了@types/webdriverio 以获得智能提示。

现在,每当我运行 tsc 工具编译项目时,都会出现以下错误:

node_modules/@types/jquery/index.d.ts(36,15): error TS2451: Cannot redeclare block-scoped variable '$'.
node_modules/@types/webdriverio/index.d.ts(1898,18): error TS2451: Cannot redeclare block-scoped variable '$'.
node_modules/@types/webdriverio/index.d.ts(1899,18): error TS2451: Cannot redeclare block-scoped variable '$'.

问题是两个包都声明了一个全局 $ 变量。您也可以在“全局值”下的 npm 页面中验证它:

https://www.npmjs.com/package/@types/jquery

https://www.npmjs.com/package/@types/webdriverio

我不明白为什么 tsc 试图将它们编译在一起,因为我没有在同一个 .ts 文件中使用 jquery 和 webdriverio?

另外,即使我注释掉了测试,所以我没有在任何地方引用 webdriverio,当我运行 tsc 时,我得到了同样的错误。可能 tsc 正在将 node_modules/@types 中的所有源代码一起编译。事实上,如果我删除 node_modules/@types/webdriverio 文件夹并再次运行 tsc,我不会收到任何错误(当然,只要我保留测试代码的注释即可)。

这是我的 tsconfig.json,它位于项目的根目录中:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs",
        "sourceMap": false,
        "inlineSourceMap": true,
        "inlineSources": true,
        "declaration": false,
        "outDir": "dist"
    },
    "include": [
        "src/**/*"
    ]
}

我所有的源代码都在 src 目录中。测试在 src/test 中。

我可以进行任何配置以在编译时将 webdriverio 和 jquery 类型分开吗?另外,我看到一些用js编写的代码示例,它们一起使用:这在打字稿中不可行吗?

【问题讨论】:

    标签: jquery node.js typescript webdriver-io


    【解决方案1】:

    好久不见,终于找到解决办法了!

    您需要定义两个单独的 tsconfig:一个用于主项目,一个用于测试。

    tsconfig.project.json

    {
        "compilerOptions": {
            "target": "ES6",
            "module": "commonjs",
            "sourceMap": false,
            "inlineSourceMap": true,
            "inlineSources": true,
            "watch": false,
            "declaration": false,
            "outDir": "dist",
            "typeRoots": ["./typings"],
        },
        "include": [
            "src/**/*"
        ],
        "exclude": [
            "src/test/*"
        ]
    }
    

    tsconfig.test.json

    {
        "compilerOptions": {
            "target": "ES6",
            "module": "commonjs",
            "sourceMap": false,
            "inlineSourceMap": true,
            "inlineSources": true,
            "watch": false,
            "declaration": false,
            "outDir": "dist",
            "typeRoots": ["./typings"],
        },
        "include": [
            "src/test/*"
        ]
    }
    

    然后,在 package.json 文件中定义两个不同的脚本来针对你刚刚定义的两个 tsconfig 运行 tsc:

    {
    ...
      "scripts": {
        "test": "tsc -p tsconfig.test.json && mocha --exit dist/test",
        "tsc": "tsc -p tsconfig.project.json",
        ...
      },
    ...
    }
    

    关键点是 typeRoots 配置,它覆盖了 typescript 编译器的默认行为。默认行为是加载在任何 @types 文件夹下定义的每个包(因此包括安装在 node_modules 文件夹中的每个 @types)。 通过覆盖此配置,node_modules 中的 @types 仅在引用时才包含在内。或者,您可以将 typeRoots 配置替换为

    "types": []
    

    来自https://www.typescriptlang.org/docs/handbook/tsconfig-json.html

    @types、typeRoots 和类型

    默认情况下,所有可见的“@types”包都包含在你的 编译。任何封闭文件夹的 node_modules/@types 中的包 被认为是可见的;具体来说,这意味着包内 ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/,等等。

    如果指定了 typeRoots,则只有 typeRoots 下的包会被 包括在内。

    ...

    指定“类型”:[] 以禁用自动包含 @types 包。

    请记住,自动收录仅在您满足以下条件时才重要 使用具有全局声明的文件(与声明为的文件相反 模块)。 例如,如果您使用 import "foo" 语句, TypeScript 可能仍会查看 node_modules 和 node_modules/@types 文件夹来查找 foo 包。

    另一个重要的一点是分离配置文件。这样,您可以在编译主项目时排除测试文件,反之亦然。这很重要,因为主项目包含 jquery,而测试文件包含 webdriverio。将它们一起编译,您会得到问题中描述的相同错误。

    【讨论】:

      猜你喜欢
      • 2016-03-17
      • 2015-07-25
      • 2020-01-15
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 2021-05-29
      • 2013-06-05
      • 2022-01-15
      相关资源
      最近更新 更多