我正在将一个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>
[...]
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
能再使用了,我还必须使用诸如RequireJS之类的东西,但我没有开始工作。我的浏览器不支持纯ES6或ES5导入。
我以为也许/// <reference types="..."
会做这项工作,但这似乎还用于其他方面。
我的希望是为编译器抱怨的内容,原因以及解决方法提供一些可理解的上下文。不幸的是,你描述的模块导入限制可能是你要解决的另一个问题(我认为AMD和SystemJS是--outFile的唯一选择,但稍后请参阅我的移植说明。)
你在问题中引用了三斜杠指令
/// <reference types="..."
这是用于告诉编译器TS声明文件(.d.ts
)中类型依赖关系的指令-并不是完全需要的,因为我们正在编写TS而不是声明文件。我们要包括一个丢失的声明文件,该文件已经存在于某处。请注意,TypeScript确实非常努力地尝试为开发人员自动解析并包含类型声明文件,但是像color-js这样的库既不在其中指定类型位置,package.json
也不使用类型或@types约定,而编译器只是“找不到它。
你可能不想通过声明全局any
变量来解决此问题,从而放弃你的智能感知优势。paths
我们可以在tsconfig.json
编译器选项中添加一个犯罪记录不足的对象,即我们可以通过这种方法通知编译器其他位置来查找类型,而不用修改诸如typeRoot或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将其转译为输出文件(读取:这是一个文件!),因此我们不必担心import关键字将其转换为生成的main.js。
假设这种配置不符合你的用例,你仍然发现自己正在寻找一种无需导入模块即可使用类型声明的方法。如果确实没有其他选择,那么使用ANY变量之类的技巧是最后的选择。
在这方面,大多数声明文件是全有或全无,因为在后台从.d.ts文件(包括color-js的文件)中实际导出的是一个可以构建Color实例的函数。这就是这let colorManager = Color();
行的全部意义,我们除了利用有关函数构建内容的类型信息之外,还利用了导出的构建器。正如你所注意到的,在运行时我们可能还不错,但是就编译器而言,如果我们不能导入类型化的函数并调用它,则构建将陷入困境。