Recently I started converting Loomo to TypeScript. Results are currently in the typescript branch.
JS code modules
The most challenging part was the support for Mozilla’s JS code modules, as they don’t fit well with the two module formats TypeScript can generate - CommonJS and AMD.
I created a module (in plain JS) that provides functionality for writing a JS code module using CommonJS syntax (the format TS compiles to).
It does two important things:
- it gives the module a
require
function that allows loading of relatively located modules - it turns exported objects (
exports.foo
) into elements ofEXPORTED_SYMBOLS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
All you need to do, is to include the JS module in your TypeScript file.
1 2 3 4 5 6 7 8 9 10 |
|
Relative file loading in require
uses the __URI__
property every JS code module provides and which is also used in the implementation of XPCOMUtils.importRelative
.
There are some things to consider.
You need to provide declarations for Mozilla specific APIs like Components.xxx
, which I do provide in MozGlobals.d.ts
(which is referenced by Moz.d.ts
). You will also have to provide the declaration for initCommonJSModule
, otherwise TypeScript won’t compile. Doh!
Also TypeScript does not support using this
in global scope, but it is the only way to access the global object of the module and thus needed. I had to hack it using eval(this)
. I considered using a function which simply returns this
, but I think this will be problematic in strict mode.
One big caveat is still there: importing modules from other contexts (like “chrome://browser” or extensions) can’t be done, as require
can only import relative to the source file. You will have to use Components.utils.import
and provide TypeScript declarations.
Some remarks: Mozilla specifics, ES6/Harmony features and host objects
As I already said, you will have to provide declarations for all Mozilla specific APIs. This includes APIs and functions that will appear with ES6/Harmony, which shouldn’t be too complicated.
Really problematic are ES6/Harmony’s syntactic changes. TypeScript currently does not support let
and const
. I opened a bug report for it, but I don’t see it happening in the near future. I’m not sure about generators and yield
either.
Also, for now, host objects like Array
can not be extended.
Conclusion
Apart from some problems here and there and missing features of ES6/Harmony, TypeScript conversion went pretty smoothly.