所以我最近攻击了一个大型的Typescript项目(https://github.com/BabylonJS/Babylon.js),我注意到他们不需要导入任何东西,他们只是使用他们的命名空间,其余的(看似)魔术。
让我觉得我想为自己使用类似的东西,所以我开始了一个简单的打字稿项目来试试。
tsconfig.json
{
"compilerOptions": {
"baseUrl": "src",
"outFile": "server.js"
}
}
src/main.ts
module Test {
console.log('Main started')
const server:Server = new Server()
}
src/Server.ts
// import * as http from 'http'
module Test {
export class Server {
constructor() {
console.log('Server initialized')
}
}
}
如果我构建这个Typescript项目,那么我得到如下输出:
// import * as http from 'http'
var Test;
(function (Test) {
var Server = /** @class */ (function () {
function Server() {
console.log('Server initialized');
}
return Server;
}());
Test.Server = Server;
})(Test || (Test = {}));
var Test;
(function (Test) {
console.log('Main started');
var server = new Test.Server();
})(Test || (Test = {}));
到目前为止,这么好。麻烦的是我想利用一些外部模块,在这种情况下是http
模块,所以我取消注释上面的导入行,现在是Typescript报告:
src/server/Server.ts(1,1): error TS6131: Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.
Node使用commonjs模块系统,因此显然设置这些标志中的任何一个都不会对我有所帮助。我没有尝试过它们以及其他各种旗帜组合,但无济于事。我注意到BabylonJS并没有真正使用这样的外部导入,而是选择将它们声明为外部导入,并在执行时将它们作为脚本标记提供给全局。是否可能与Node类似?
答案 0 :(得分:1)
你不能同时拥有这两件事,即
如何避免总是在Typescript中导入我自己的代码?
和
我想利用一些外部模块
您可以仅通过不使用外部模块来避免导入,结果将是一个巨大的脚本文件,只能将外部依赖项用作通过script
标记加载的脚本创建的全局变量,正如您已经注意到的那样。
执行此操作时,该语言不允许您使用外部模块。如果您在顶层导入外部模块,则您的文件将成为一个模块,并且无法在不导入其他文件的情况下使用其他文件中的代码。并且不允许在命名空间内导入外部模块AFAIK。
那就是说,我不会想你的问题 - "我怎样才能避免总是必须在Typescript中导入我自己的代码?" - 有一个有效的前提。 CommonJS模块系统是防止大型项目变得难以维护的混乱的解决方案。如果项目的某些部分是您自己的代码或某些外部依赖项并不重要 - 如果它是具有定义良好的接口的单独部分,则应将其打包并作为模块使用。
答案 1 :(得分:0)
对我有用的解决方案是:
Server.ts
declare var http: any;
namespace Test {
export class Server {
constructor() {
console.log('Server initialized')
const server = http.createServer()
server.listen()
}
}
}
然后我只是在运行时提供http
,例如通过在输出前加var http = require('http')
。感谢artem在正确的方向上轻推。