Aggregating and Exposing Types

Topics: General
Feb 27, 2013 at 5:48 PM
Hi. I'm working on moving an existing solution of > 1,000 classes and several projects to TypeScript. Currently each class is in its own file and assigned to the global namespace under something like company.foo.bar.Class. These files are concatenated together as a compile step. So I'm not just moving the project to TypeScript I'm moving it to AMD as well.

I want to keep each class in its own file but importing each class individually and always referring to it with an arbitrary prefix strikes me as awkward. To that end I thought it would be useful to have modules that aggregate related classes. eg:
// alphabet/abc/Alpha.ts
export class Alpha {
    private greeting: String;
    constructor(greeting: String) {
        this.greeting = greeting;
    }
    greet(): String {
        return this.greeting;
    }
}
// alphabet/abc/Bravo.ts
export class Bravo {
    private greeting: String;
    constructor() {
        this.greeting = "Bravo don't take no constructor";
    }
    greet(): String {
        return this.greeting;
    }
}
// alphabet/abc/index.ts
// This file would be trivial to generate
import alpha = module("alphabet/abc/Alpha");
export var Alpha: new (String) => alpha.Alpha = alpha.Alpha;

import bravo = module("alphabet/abc/Bravo");
export var Bravo: new () => bravo.Bravo = bravo.Bravo;
And now over in an application class I can do this:
import abc = module("alphabet/abc/index");
var a = new abc.Alpha("Hello world");
document.getElementById('content').innerText += a.greet();
So that looks pretty cool because the pattern feels comfortable, the generated JavaScript does exactly what you'd hope, VS finds the type and the "a" var gets autocomplete. The only problem is that abc.Alpha is a constructor but not a type so either of these are compile errors:
var a: abc.Alpha = new abc.Alpha("Hello world");
function foo(bar: abc.Alpha): void { }
In fact there's nothing I can put in for those types without importing the original class. Is there a reason the constructor shouldn't be usable as a type? It feels like given the way JavaScript works it should be safe. Is there a better way to accomplish what I'm trying to do here?

Cheers.
Coordinator
Mar 1, 2013 at 4:08 PM
We've seen some variations on this, and they end in about the same pain point. You need to be able to set what exactly you want to export. In your case, it looks like you want to be able to export a class as the external component that is imported.

In module systems, it's not uncommon to want to do this by assigning to the exports and replacing the default object. In Node it's "module.exports = ???"

We're looking into ways to do something similar in TypeScript where you can set the symbol you want to export, and it will export not just that symbol but also its type information. This would give you a more straightforward way to put one class in each external module.
// Alpha.ts
class Alpha { ... }
export = Alpha;

// main.ts
import ExternalAlpha = module("Alpha");
var a = new ExternalAlpha();