TypeScript和d3

15

我有一个使用d3库的应用程序。在TypeScript代码中,为了成功使用d3(即避免编译器错误TS2686,因为d3引用了UMD全局变量,但当前文件是模块),我必须包含以下行:import * as d3 from 'd3';

问题是这会在JavaScript中发出:require('d3');。这并不是我们应用程序中d3库的位置。它位于Web应用程序的根目录下,名为“d3”的目录中。而且,我根本不需要它出现在JavaScript中,因为我们的index.html已将其作为全局加载。

我很难弄清楚如何使TypeScript源码允许我引用d3,而无需导入它。


1
听起来你正在将 d3 作为全局变量使用,而不是作为模块。首先,为什么不将其作为模块使用(例如使用 npm 安装)?如果你想从模块内部作为全局变量使用 D3,我认为你需要手动将其声明为全局变量。 - Aaron Beall
我可以将其声明为全局变量,但是TypeScript就无法理解我执行d3.selectAll(...)之类的操作了。我安装了d3 typings,它们位于node_modules/@types下,由npm install放置在那里。d3的index.d.ts将d3声明为一个命名空间。编辑器中已经解决了所有问题,但是在引用d3时会出现错误。但是,在编辑时,TypeScript环境已知d3声明的所有内容。 - rdiddly
了解类型与代码实际工作是不同的。你是如何将D3包含到你的项目中的? - Aaron Beall
这是一个相当庞大的项目,主要使用JavaScript编写,使用了很多dojo和d3,并且我们有一个新的小部件层次结构正在开发中,已经有几周时间了,正在使用TypeScript编写。d3代码打包到Web应用程序根目录下的d3目录中。TypeScript源代码编写在源代码树中,位于WebContent文件夹之外,并被编译为WebContent层次结构。通过tsconfig.json配置TypeScript源码以理解d3类型定义在node_modules/@types/d3下。应用程序运行时没有错误。谢谢你的帮助。 - rdiddly
我相信你仍然可以将其标记为已接受。 :) - Aaron Beall
显示剩余3条评论
2个回答

24

你有两个可能的选择:

抑制警告

TypeScript 3.5 开始,添加了 --allowUmdGlobalAccess 标志,允许您从模块文件中访问全局定义。在你的情况下,这意味着你可以使用 d3 作为全局命名空间,而不需要 importrequire 语句。这显然适用于项目中的所有模块文件和任何其他 UMD 类型定义(例如 React),因此请注意,根据你的代码设置和使用的库,它可能不在所有上下文中正确。

声明全局命名空间

在 TS 3.5 之前且没有 --allowUmdGlobalAccess 标志的情况下,UMD 类型定义无法在模块文件中作为全局命名空间引用。(它只允许你从非模块文件中引用全局命名空间。)这是一种有意的安全保护措施,以防止意外引用在严格基于模块的项目中不可用的全局命名空间。解决方法 是在你的项目中手动声明一个全局命名空间:

// global.d.ts
import * as _d3 from "d3";

declare global {
  const d3: typeof _d3;
}

现在,您可以在模块中引用d3,而无需从"d3"导入它,并且您仍然应该基于@types/d3获得d3对象的所有正确类型检查。
--allowUmdGlobalAccess相比,这具有优势,因为它非常明确地说明了您特定的代码设置。换句话说,它不会无意中让您编译其他您的代码设置未全局提供的UMD模块。

2
DefinitelyTyped是目前使用TypeScript和D3的最佳方法。如果您想要更通用的解决方案,可以使用Aaron Beall提供的答案。请注意保留HTML标签。
npm i d3
npm i -D @types/d3

并且

import * as d3 from 'd3';

就像使用任何其他@types库一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接