我怎样才能避免总是必须在 Typescript 中导入我自己的代码?

How can I avoid always having to import my own code in Typescript?

所以我最近正在研究一个大型 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 模块系统,因此显然设置这些标志中的任何一个都不会对我有太大帮助。我已经 none 尝试了 less 以及其他各种标志组合,但无济于事。我注意到 BabylonJS 并没有像那样真正使用外部导入,而是选择将它们声明为外部导入,并在执行时将它们作为脚本标签全局提供。是否有类似的 Node?

你不能同时拥有这两个东西,即

How can I avoid always having to import my own code in Typescript?

I want to take advantage of some external modules

您只能通过不使用外部模块来避免导入,结果将是一个巨大的脚本文件,它只能将外部依赖项用作通过 script 标记加载的脚本创建的全局变量,正如您已经注意到的那样。

该语言不允许您在执行此操作时使用外部模块。如果你在顶层导入了外部模块,你的文件就变成了一个模块,如果不导入它们,它就无法使用其他文件中的代码。 AFAIK 不允许在命名空间中导入外部模块。

也就是说,我认为您的问题 - "How can I avoid always having to import my own code in Typescript?" - 没有有效前提。 CommonJS 模块系统是防止大型项目变得无法维护的混乱的解决方案。项目的某些部分是您自己的代码还是某些外部依赖项并不重要——如果它是具有定义良好接口的独立部分,则应将其打包并作为模块使用。

对我有用的解决方案是:

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 在正确方向上的推动。