In our pre-existing codebase, we use the "classes are Functions and Functions are Objects" aspect of JavaScript to do namespacing.
E.g., suppose we have a class named Foo, that contains a class named Bar.
Foo is a globally exported object, (i.e, it exists at window.Foo), and window.Foo.Bar is the constructor for Bar. (I think it's fair to say that this is a common JavaScript pattern).
It's true that this pattern creates a directional dependency. Foo must be loaded before Bar. We accomplish this using stealjs, an asynchronous module loader that is not conformant with AMD protocol. For this reason, we cannot use TypeScript's built-in import/export AMD code generation. At least, not until we do several weeks worth of drudgery to port our entire code base to requirejs.
To match this pattern in TypeScript, we speak of a class named Foo, and also a module named Foo.
class Foo {
/* Foo's properties */
}
module Foo {
export class Bar {
/* Bar's properties */
}
}
This is legal TypeScript and it compiles to the JavaScript situation described above: the Foo class object will contain the Bar class object as its "Bar" property. The Foo module is said to merge with the Foo class, and Bar is said to be an inner class.
However, if I simply separate these two statements into separate files:
// Foo.ts
class Foo {
/* Foo's properties */
}
// Foo/Bar.ts
module Foo {
export class Bar {
/* Bar's properties */
}
}
This is no longer legal TypeScript, and it doesn't compile. [1] (This despite the fact that we could and would arrange for the second file to be loaded after the first file loads via our own module loader.)
This is a big problem for us, because we're not about to smoosh all of our inner class declarations into one file. As far as I can tell, there is actually no solution to this. We simply have to pollute the global namespace and cannot merge inner classes with our namespaces.
If we were using TS's built in import/export semantics this problem wouldn't come up, but we aren't, for the reason described above. Porting everything to requirejs is not on the table right now. Given our situation, what do you think is the best strategy for working around the class-module merging restriction?
[1]TypeScript: Module x cannot merge with previous declaration of x in a different file
Foo
and classFoo
). Could you come up with a similar strategy: independent compilation using a script then merging ? – Bruno Grieder