Search code examples
node.jstypescriptcommonjs

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


So I was recently hacking on a large Typescript project (https://github.com/BabylonJS/Babylon.js) and I noticed that they don't ever have to import anything, they just use their namespace and the rest is (seemingly) magic.

It got me thinking that I would like to use something similar for myself, so I started a simple typescript project to try it out.

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')
    }
  }
}

If I build this Typescript project then I get output like the following:

// 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 = {}));

So far, so good. The trouble is that I want to take advantage of some external modules, in this case namely the http module, so I uncomment the import line above and now Typescript reports:

src/server/Server.ts(1,1): error TS6131: Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.

Node uses the commonjs module system, so obviously setting either of those flags isn't going to help me much. I have none the less tried them as well as various other combinations of flags, but to no avail. I noticed that BabylonJS doesn't really use external imports like that, opting instead to declare them as external and provide them globally at execution time as script tags. Is there maybe an analogue to that for Node?


Solution

  • The solution that worked for me is this:

    Server.ts

    declare var http: any;
    
    namespace Test {
      export class Server {
        constructor() {
          console.log('Server initialized')
          const server = http.createServer()
          server.listen()
        }
      }
    }
    

    Then I simply provide http at runtime, for example by prepending a var http = require('http') to the output. Thanks to artem for a nudge in the right direction.