iFr*_*cht 7 javascript import types typescript tsc
我正在将Web应用程序从普通Javascript迁移到Typescript,并使用--outFile编译器选项和/// <reference path="..."/>指令将所有单独的文件编译为单个文件.
这很好,因为我可以将我的代码分成多个文件,而不必担心浏览器支持import.
我使用的一个库是color-js,它在一个名为的文件中有类型定义color.d.ts.
要使用普通的Javascript,我会执行以下操作:
[...]
<script src="scripts/color-js/color.js"></script>
<script src="main.js"></script>
[...]
Run Code Online (Sandbox Code Playgroud)
let Color = net.brehaut.Color;
[...]
Run Code Online (Sandbox Code Playgroud)
在运行时,这也适用于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'.
Run Code Online (Sandbox Code Playgroud)
有没有办法只使用类型定义color.d.ts来定义编译时的类型,而不将其作为模块导入?
一旦我将它作为一个导入,我就不--outFile能再使用了,我也必须使用像RequireJS这样的东西,我没有去工作.我的浏览器不支持普通的ES6或ES5导入.
我想也许/// <reference types="..."可以做那个工作,但这似乎是用于别的东西.
我希望在这里为编译器抱怨的内容、原因以及如何解决提供一些易于理解的上下文。不幸的是,您描述的模块导入限制可能是您要解决的不同问题(我认为 AMD 和 SystemJS 将是您使用 --outFile 的唯一选择,但稍后请参阅我的转译说明。)
您在问题中引用了三斜线指令
/// <reference types="..."
Run Code Online (Sandbox Code Playgroud)
这是用于告诉编译器有关 TS 声明文件 ( .d.ts)内的类型依赖关系的指令——不是完全需要的,因为我们正在编写 TS 而不是声明文件。我们想要包含一个已经存在于某处的缺失声明文件。请注意,TypeScript 确实非常努力地尝试为开发人员自动解析和包含类型声明文件,但是像 color-js 这样的库没有在其中指定类型位置,package.json也没有使用类型或 @types 约定,编译器只是“ t能够找到它。
您可能不想通过声明全局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"]
}
Run Code Online (Sandbox Code Playgroud)
该paths条目告诉编译器解析字符串“color-js”的任何导入,而不是将模块解析为 JS 文件,而是从指定路径中获取 color.d.ts 作为所需模块。
以下是示例 TS(或 JS!)文件的外观:
import Color from "color-js";
let colorManager = Color();
let twenty = colorManager.setRed(20).getRed();
Run Code Online (Sandbox Code Playgroud)
虽然这个解决方案使用了 import 关键字,但一个想法是,因为我们正在使用上面的 tsconfig.json 转换为一个输出文件(阅读:它是一个单独的文件!),我们不必担心导入关键字将其转换为由此产生的 main.js。
假设此配置不符合您的用例,并且您仍然发现自己正在寻找一种无需导入模块即可使用类型声明的方法。如果你真的没有其他选择,使用像 any-typed 变量这样的 hack 是最后的手段。
大多数声明文件在这方面要么全有要么全无,因为实际上从幕后的 .d.ts 文件(包括 color-js)导出的是一个可以构建 Color 实例的函数。这就是该let colorManager = Color();行的全部内容,除了有关函数构建内容的类型信息之外,我们还使用了导出的构建器。正如您所注意到的,在运行时我们可能仍然没问题,但是就编译器而言,如果我们无法导入类型化函数并调用它,那么构建就毫无意义了。
Typescript 3.8 使用以下import type {} from '...'语法添加了此功能:
import type 只导入用于类型注释和声明的声明。它总是会被完全擦除,因此在运行时不会有任何残留。同样,导出类型仅提供可用于类型上下文的导出,并且也会从 TypeScript 的输出中删除。
需要注意的是,类在运行时有一个值,在设计时有一个类型,并且使用是上下文相关的。使用导入类型导入类时,您不能对其进行扩展等操作。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html
| 归档时间: |
|
| 查看次数: |
1305 次 |
| 最近记录: |