3

Apologies for any incorrect terminology. For those not familiar with Meteor, it has a well-defined order of script loading. I'm trying to create many *.ts files containing a class, like you'd see in C#'s *.cs files. I want to reference these *.ts files between each other, and ultimately from a main.ts.

Compiling Car.ts:

class Car {
   constructor(public age: number) { }
}

Generates Car.js:

var Car = (function () {
    function Car(age) {
        this.age = age;
    }
    return Car;
})();

With Meteor, I want the following output:

Car = (function () {
    function Car(age) {
        this.age = age;
    }
    return Car;
})();

So that Car can be referenced from another file, main.ts:

/// <reference path="car.ts"/>
Meteor.startup(function () {
    console.log(Car); // Hopefully prints [Function: Car]
    var a: Car = null; // Compiles
});

I can get close by modifying Car.ts:

declare var Car;

class Car_ {
   constructor(public age: number) {}
}

Car = Car_;

But this produces a kludgy output:

var Car_ = (function () {
    function Car_(age) {
        this.age = age;
    }
    return Car_;
})();
Car = Car_;

And necessitates a kludgy main.ts:

/// <reference path="car.ts"/>
Meteor.startup(function () {
    console.log(Car); // Prints [Function: Car_]
    var a: Car_ = new Car(); // Yuck!
});

Any advice? I might be treating this like too much like a C# application.

Community
  • 1
  • 1
Warty
  • 6,709
  • 1
  • 26
  • 47
  • Sounds like an XY problem... TS wraps everything in an IIFE, can't you just export `Car`? – elclanrs Mar 18 '15 at 06:27
  • I don't want to clutter the codebase with underscores under every other type token. In the above code, you have to write `var a: Car = new Car_()`which is pretty terrible. Ideally I'd be able to write something like `declare var Car = class Car {}`. – Warty Mar 18 '15 at 06:31
  • I'm aware of AMD/CommonJS modules but have struggled to find example codebases which also use Meteor (and after that, I'd want them to work on both client-side and server-side?). – Warty Mar 18 '15 at 08:02

5 Answers5

1

One solution involves setting the global object:

class Car {
   constructor(public age: number) {}
}

global.Car = Car;

which compiles to:

var Car = (function () {
    function Car(age) {
        this.age = age;
    }
    return Car;
})();
global.Car = Car;

I'm not very happy with this solution because global is a nodejs-specific thing and won't work in a browser, which uses window. It turns out this works both in-browser and on server:

class Car {
   constructor(public age: number) {}
}

this.Car = Car;

Compiles to:

 var Car = (function () {
    function Car(age) {
        this.age = age;
    }
    return Car;
})();
this.Car = Car;

Inelegant, but better...

Warty
  • 6,709
  • 1
  • 26
  • 47
0

I just had the same problem yesterday. I was using meteortypescript , which was giving me the same kind of problems (it seems like it does not allow to work properly with packages).

I switched to another compiler script, and everything works fine now. Here it is : mologie:typescript, .

I did not look long for ways to solve the problem with the first one, but I stumbled upon a discussion between the authors of the two compiler plugins, that may explain some differences : https://github.com/mologie/meteor-typescript/issues/1

May be that will help

Pascal T.
  • 3,432
  • 3
  • 29
  • 31
0

I have dealt with this issue on my blog and here. I decided to use the evil eval command, since it gave me the easiest possibility of using modules till something more sophisticated appears.

File /lib/foo.ts. It is positioned in the subdirectory since it has to be loaded before Bar as it is extending Foo.

eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
  export class Foo {
    foo():string {
      return 'foo'
    }
  }
}

File /bar.ts

/// <reference path="lib/foo.ts"/>
eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
 export class Bar extends Foo {
    bar () : string {
      return 'bar';
    }
  }
}

File /test.ts

/// <reference path="lib/foo.ts"/>
/// <reference path="bar.ts"/>

var m = new Hugo.Bar();
console.log(m.bar());
console.log(m.foo());

As mentioned before, for classes the solution is even simpler:

class ExportedClass {
    variable : int;
} 
this.ExportedClass = ExportedClass;
Community
  • 1
  • 1
tomitrescak
  • 903
  • 10
  • 21
0

scrap TS and Meteor would only run the .js files anyways.

Use https://atmospherejs.com/universe/modules instead.

-1

I might be treating this like too much like a C# application.

Yes. Removing the var from var Car has no change in this particular case (both are global).

The following will work fine. Just move car.ts into a sub folder:

/// <reference path="./foo/car.ts"/>
Meteor.startup(function () {
    console.log(Car); // Hopefully prints [Function: Car]
    var a: Car = null; // Compiles
});
basarat
  • 207,493
  • 46
  • 386
  • 462
  • I've pushed a barebones example here: https://github.com/ItzWarty/simplemeteor and am getting this error: http://puu.sh/gF9A2/954dc2b17c.png - I believe this is because Car.js's `var` makes the `Car` class at the script-block level, meaning it's not accessible to main.ts's context. – Warty Mar 18 '15 at 07:56