繁体   English   中英

使用 .d.ts 文件中的类型定义而不导入

[英]Use type definitions from .d.ts file without importing

我正在将 Web 应用程序从纯 Javascript 迁移到 Typescript,并使用--outFile编译器选项和/// <reference path="..."/>指令将所有单独的文件编译成一个文件。

这很好,因为我可以将代码拆分为多个文件,而不必担心支持import的浏览器。

我使用的一个库是color-js ,它在名为color.d.ts的文件中有类型定义。

要在纯 Javascript 中使用它,我执行以下操作:

索引.html:

[...]
<script src="scripts/color-js/color.js"></script>
<script src="main.js"></script> 
[...]

main.js/main.ts

let Color = net.brehaut.Color;
[...]

在运行时,这也适用于 Typescript,但在编译期间,我收到如下错误:

scripts/cue.ts(4,13): error TS2304: Cannot find name 'net'. 
scripts/cue.ts(25,18): error TS2304: Cannot find name 'Color'. 
scripts/cue.ts(26,16): error TS2304: Cannot find name 'Color'.
scripts/cue.ts(27,19): error TS2304: Cannot find name 'Color'. 
scripts/main.ts(839,52): error TS2304: Cannot find name 'Color'. 
scripts/main.ts(1019,20): error TS2304: Cannot find name 'Color'. 
scripts/main.ts(1022,16): error TS2304: Cannot find name 'Color'.

有没有办法只使用color.d.ts的类型定义来定义编译时的类型,而不将其作为模块导入?

一旦我将它作为一个导入,我就不--outFile使用--outFile并且我还必须使用像 RequireJS 这样的东西,但我没有开始工作。 我的浏览器不支持纯 ES6 或 ES5 导入。

我想也许/// <reference types="..."可以完成这项工作,但这似乎用于其他用途。

我希望在这里为编译器抱怨的内容、原因以及如何解决提供一些易于理解的上下文。 不幸的是,您描述的模块导入限制可能是您要解决的不同问题(我认为 AMD 和 SystemJS 将是您使用 --outFile 的唯一选择,但稍后请参阅我的转译说明。)

您在问题中引用了三斜线指令

/// <reference types="..."

这是用于告诉编译器有关 TS 声明文件 ( .d.ts ) 内的类型依赖关系的指令——不是完全需要的,因为我们正在编写 TS 而不是声明文件。 我们想要包含一个已经存在于某处的缺失声明文件。 请注意,TypeScript 真的非常非常努力地尝试为开发人员自动解析和包含类型声明文件,但是像 color-js 这样的库没有在package.json指定类型位置,也没有使用类型或 @types 约定,编译器只是无法找到它。

您可能不想通过声明全局any变量来解决此问题来放弃您的智能感知优势。 有一个称为paths的犯罪记录不足的对象,我们可以将其添加到我们的tsconfig.json编译器选项中,这就是我们如何通知编译器其他位置来查找类型,而不是修改 typesRoot 或 types 选项等自动加载行为。 这是一个似乎运行良好的示例tsconfig.json文件:

{
    "compilerOptions": {
        "module": "system",
        "target": "es5",
        "allowJs": true,
        "outFile": "./dist/main.js",
        "rootDir": "./src",
        "baseUrl": "./",
        "paths": {
            "*": ["color-js", "./node_modules/color-js/color.d.ts"]
        }
    },
    "exclude": ["dist"]
}

paths条目告诉编译器是解析字符串“color-js”的任何导入,而不是将模块解析为 JS 文件,而是从指定路径中获取 color.d.ts 作为所需模块。

以下是示例 TS(或 JS!)文件的外观:

import Color from "color-js";

let colorManager = Color();

let twenty = colorManager.setRed(20).getRed();

虽然这个解决方案使用了 import 关键字,但一个想法是,由于我们正在使用上面的 tsconfig.json 转换为一个输出文件(阅读:它是一个单独的文件!),我们不必担心导入关键字将其转换为由此产生的 main.js。

假设此配置不符合您的用例,您仍然发现自己正在寻找一种无需导入模块即可使用类型声明的方法。 如果你真的没有其他选择,使用像 any-typed 变量这样的 hack 是最后的手段。

大多数声明文件在这方面要么全有要么全无,因为实际上从幕后的 .d.ts 文件(包括 color-js)导出的是一个可以构建 Color 实例的函数。 这就是let colorManager = Color(); line 的全部内容是,除了有关函数构建内容的类型信息之外,我们还使用导出的构建器。 正如您所注意到的,在运行时我们可能仍然没问题,但是就编译器而言,如果我们无法导入类型化函数并调用它,那么构建就无济于事了。

Typescript 3.8 使用import type {} from '...'语法添加了此功能:

import type 只导入用于类型注释和声明的声明。 它总是会被完全擦除,因此在运行时不会有任何残留。 同样,导出类型仅提供可用于类型上下文的导出,并且也会从 TypeScript 的输出中删除。

需要注意的是,类在运行时有一个值,在设计时有一个类型,并且使用是上下文相关的。 使用导入类型导入类时,您不能对其进行扩展等操作。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM