【问题标题】:TypeScript compilerOptions.types with a module带有模块的 TypeScript compilerOptions.types
【发布时间】:2018-12-29 00:07:03
【问题描述】:

我有一个 JavaScript 项目,可以简化成这样:

console.log(depA());
console.log(depB());

我正在使用普通的旧 script 标签来引入依赖项:

<html>
  <head>
    <script src="pkg/depA/index.js"></script>
    <script src="pkg/depB/index.js"></script>
    <script src="src/index.js"></script>
  </head>
</html>

我使用的包是JavaScript包,都是这样的:

function depX() { // Where X is A or B
  return 'depX';
}

这两个包都有自己的index.d.ts typings alongside theirindex.js`。

对于包 A,这很简单:

declare function depA(): string;

对于也可以作为模块使用的包B,typings也是一个模块文件:

declare function depB(): string;
export default depB;

就像我说的,这是一个 JavaScript 项目,我正在使用 TypeScript 进行类型检查:

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
    "types": [
      "../pkg/depA",
      "../pkg/depB",
    ]
  }
}

我使用 compilerOptions.types 引用包类型,因为这是一个纯 JavaScript 项目,我没有使用 NPM 或任何东西来安装包或类型,因为这是 JavaScript 代码,所以没有 import语句或requires(我没有使用 ESM,也没有 CJS 的构建过程),因此 TypeScript 无法知道这些包并且知道以任何其他方式提取它们的类型,但使用compilerOptions.types 明确告知。

问题是,包 B 的类型是模块文件,所以 depB 函数是在模块范围内声明的,而不是在窗口范围内。 depAdepB 只是演示,我面临着现实世界的包,所以我没有选择删除 export default 并使打字成为非模块文件,但我可以创建一个拉请求并添加支持,以使打字文件既是窗口全局函数,又是其他消费者完全使用的模块可以导入的模块。

我的问题然后是,如何修改 depB 类型以使其仍然是一个模块文件(并且没有现有的消费者被破坏),但它们也传达 depB 函数存在于窗口范围,所以 TypeScript 知道可以就地调用它,独立,不导入,什么都没有?

在运行时,就是这样,所以打字是问题,他们只是不传达这个让 TypeScript 知道(我认为),所以我问,如何改变它们来做到这一点?

我创建了一个 GitHub repository 来演示问题,有一个关联的公共 Azure 管道运行 TypeScript 类型检查,显示 depA 可以毫无问题地访问,但 depBwindow 处不可见因为它只是作为一个模块进行通信。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您所描述的模式通常用于定义 UMD 包。可以导入它们的内容,或者——如果没有模块捆绑器——从全局范围访问。

    TypeScript handbook 解释了他们的定义应该是什么样子。您的案例在module-function.d.ts 模板中定义,可以简化为:

    depB.d.ts

    declare function depB(): string;
    
    export as namespace depB;
    export = depB;
    

    在您的项目中包含上述内容为我完成了这项工作,并且不需要上游更改。

    请参阅pull request

    【讨论】:

    • 这是否可以与export default 协调?它已经存在于我正在使用的上游库中,并且正在寻求对全局范围访问的支持,但是当应用于depB/index.d.ts 时,上述解决方案表示 导出分配不能在具有其他导出元素的模块中使用。我想这是一个合法的限制,所以如果不可能的话,我会使用你在分支中的本地文件(谢谢!),但我还是很好奇。
    • 错误是正确的——您不能将export = 与任何 ESM 导出一起使用。但是,您可以通过在 tsconfig.json 中启用 allowSyntheticDefaultImports 标志来使 TypeScript 将此导出视为默认导出。在这种情况下,上述类型可以上游(pkg/depB/index.d.ts)并且不需要本地文件。请参阅pull request
    猜你喜欢
    • 2020-01-06
    • 2016-01-24
    • 2016-04-11
    • 2012-11-16
    • 1970-01-01
    • 2017-06-14
    • 2016-07-29
    • 2019-07-03
    • 2017-10-13
    相关资源
    最近更新 更多