【问题标题】:Importing any .d.ts results in runtime error导入任何 .d.ts 都会导致运行时错误
【发布时间】:2018-04-14 02:50:43
【问题描述】:

我在 TypeScript 中缺少一些简单的东西......

使用 Chrome 运行我的代码,我有一个工作的打字稿环境,我的所有其他代码/模块都按预期工作。

当我从 .d.ts 导入时,所有内容都编译时没有错误/警告,但我在 Chrome 中遇到运行时错误,因为生成的 JavaScript 正在尝试从不存在的文件导入。

import { doSomething } from "exampleJsLibrary";

在浏览器中失败,因为 TypeScript 不会将 exampleJsLibrary.d.ts 转换为 JS 文件。

我的目标是 es5,使用 es6 模块输出,并使用 tsc 构建(没有 webpack/browserify 工具),ts 2.7.2。

完整示例:

<!DOCTYPE html>
<html>
    <head>
    <script>
            var exampleJsLibrary = (function() {
                return {
                    doSomething: function(x) { return x + 1 }
                }
            })()
    </script>
    <script type="module" src="./built/myCode.js"></script>
    </head>
    <body>
    </body>
</html>

和

// exampleJsLibrary.d.ts
export const doSomething(x: number): number;
export as namespace exampleJsLibrary;


// myCode.ts
import { doSomething } from "./exampleJsLibrary";
function test() {
    console.log(doSomething(3));
}

// tsconfig.json
...
        "target": "es5",
        "lib": ["dom", "es5", "es2015.iterable", "es2015"],
        "outDir": "built",
        "module": "es6"
...

失败是因为为 myCode.js 生成的代码 还有import { doSomething } from "./exampleJsLibrary"这行, 这会导致运行时错误,因为没有 exampleJsLibrary 或 exampleJsLibrary.js。 如果我将生成的 JS 中的那一行替换为 var doSomething = exampleJsLibrary.doSomething,一切正常。

如何从 .d.ts 导入?

【问题讨论】:

  • 导入d.ts 文件通常是使用triple slash directive 完成的,因此如果您要导入的只是类型,请尝试添加一行/// &lt;reference path="./exampleJsLibrary" /&gt;(具有正确的相对路径)而不是使用导入语法。但是,确保您使用的任何东西在运行时都存在是另一回事。
  • 从您的示例来看,exampleJsLibrary 似乎只是在脚本标记中声明为全局变量——在实际代码中也是这样吗?
  • 在整个项目中,它是从一个创建全局的JavaScript文件中包含的,效果是一样的。

标签: typescript


【解决方案1】:

.d.ts declaration files 只包含类型声明,而不是实际代码。 (它们就像 C/C++ 中的头文件,如果您碰巧熟悉的话。)您需要在项目中包含实际的库代码,然后将其导入或全局定义以使其在运行时工作.

在您的情况下,由于库代码作为全局包含在页面中,因此您不需要使用import。相反,您可以说:

const doSomething = exampleJsLibrary.doSomething

如果编译器抱怨 exampleJsLibrary 未定义,最简单的解决方法是将其添加到文件顶部(使用 .d.ts 的实际相对路径):

/// <reference path="path/to/exampleJsLibrary" />

(请注意,如果您的包是从 npm 中包含的,则方法会有所不同,这很常见。)

【讨论】:

  • 是的,实际代码在运行时可用。它是全局命名空间中的一个 JavaScript 对象。
  • 谢谢!更新。如果有任何不清楚的地方或者您开始​​遇到编译器错误,请告诉我——如果是这样,这可能意味着声明文件错误地将库定义为模块而不是全局。
  • 使用 /// 似乎可以解决所有问题。
猜你喜欢
  • 2022-09-25
  • 2016-01-06
  • 2017-04-03
  • 2017-05-28
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
相关资源
最近更新 更多