TypeScript namespacing and modules

Topics: General, Language Specification
Dec 17, 2012 at 10:17 PM

To the best of my understanding, a module is conceptually similar to an assembly in C#. That is, it is a reusable package of code that can be referenced where needed.

I have been trying to use modules as I would have namespaces in C#, but this leads to pretty ugly code (notably: lots of wrapper code for the module definitions, lots of tedious repetitions to import other modules and lots of ugly module prefixes).

It seems to me as if TypeScript lacks a feature that corresponds to namespaces - a way to conceptually organize your code into logically separate parts. Using modules as namespaces seems wrong as it really was designed for exposing libraries to external consumers, rather than being a language feature to help organize the internal structure of a library or application.

Am I overlooking something?

Note: related question posted on stackoverflow.com

Coordinator
Dec 18, 2012 at 4:52 PM

Modules serve a few roles (in some ways they seem a bit overloaded).  For example, when using AMD, they're a way to structure your program into loadable modules.  Used that way, they tend to get called "external" modules. 

There are also the "internal" modules which serve similar roles to modules and namespaces in other languages.  These allow you to sort your code into separate modules for code organization and cleanliness.  Like you say, you can use these for group related functionality for customers, too. 

 

Dec 18, 2012 at 8:18 PM

I am currently using internal modules.

However, it feels clunky and ill suited for code organization due to the fact that you cannot implicitly import types defined in other modules - you have to prefix type names with module names. I'd still like to separate my code into smaller modules, but not at the current syntactical cost of doing so.

Dec 19, 2012 at 4:21 PM

> lots of wrapper code for the module definitions

This was something that struck me when we first started using TypeScript, but kind of slipped into the background in the light of other issues. If you have say ten projects, each containing five TypeScript files; and each file exports a single class into a common namespace say "my.classes" then there will be 49 redundant "var my" declarations, as well as a lot more superficial code. This is highlighted in red below. 


// TypeScript

module my.classes {
	export class Bleeter {}
}

module my.classes {
	export class Greeter {	}   
}

// Compiled JavaScript

var my;
(function (my) {
    (function (classes) {
        var Bleeter = (function () {
            function Bleeter() { }
            return Bleeter;
        })();
        classes.Bleeter = Bleeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));
var my;
(function (my) {
    (function (classes) {
        var Greeter = (function () {
            function Greeter() { }
            return Greeter;
        })();
        classes.Greeter = Greeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));

I think this is something that needs to be optimised by the compiler, otherwise we are delegating a lot of important work to the bundling mechanism.

 

> lots of tedious repetitions to import other modules

   Only relevant if you are using external modules. However, having to use the <reference> include comment is also not very satisfactory.

> lots of ugly module prefixes

You can declare a using statement like below:

module my.interfaces {
	export interface IFoo {}
}

using my.interfaces; // Using declaration

module my.classes {
	export class Bleeter implements /*interfaces.*/IFoo {}
}

module my.classes {
	export class Greeter implements /*interfaces.*/IFoo {	}   
}

 

Sorry, cruel joke: you can't do that just yet! :D

IMO (and as JonTurner has been at pains to stress) these are nice to have features rather than critical issues and are not likely to be fixed any time soon.

However, since it says on the homepage "TypeScript supports tools for large-scale JavaScript applications", I would think issues such as these certainly affect scalability, because one needs to be able to organise the code-base in a meaningful way; and hence should be given some priority.

Noel

Dec 19, 2012 at 8:34 PM

Noel, there's an issue with the compiler optimizing the use of modules.  Modules create a closure scope around the class definition that can be useful for defining stuff private to the file.  The problem is if you automatically merge all of these module definitions you're also merging all of the closure scopes which could be dangerous. 

For instance, in the example below what would you expect the compiler to do about the className variable?  The code works as expected now but if the modules were merged it would stop working as expected.

Typescript:

module my.classes {
	var className = "my.Classes.Bleeter";
	
	export class Bleeter { 
		public name(): string {
			return className;
		}
	}
}

module my.classes {
	var className = "my.Classes.Greeter";
	
	export class Greeter {	
		public name(): string {
			return className;
		}
	}   
}

Generated JavaScript:

var my;
(function (my) {
    (function (classes) {
        var className = "my.Classes.Bleeter";
        var Bleeter = (function () {
            function Bleeter() { }
            Bleeter.prototype.name = function () {
                return className;
            };
            return Bleeter;
        })();
        classes.Bleeter = Bleeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));
var my;
(function (my) {
    (function (classes) {
        var className = "my.Classes.Greeter";
        var Greeter = (function () {
            function Greeter() { }
            Greeter.prototype.name = function () {
                return className;
            };
            return Greeter;
        })();
        classes.Greeter = Greeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));

Dec 19, 2012 at 8:39 PM

I would expect the compiler to issue an error for a duplicate variable definition.

The example also seems a bit contrived, considering that it's probably not good behavior to declare state outside of classes (even if the underlying mechanism for capturing the state is the same for classes as for modules).

Dec 19, 2012 at 9:50 PM

I would disagree with the compiler issuing an error.  While this example is a bit contrived the behavior is useful.  This is essentially how you define truly private classes, functions, and state.  And I'm about to post an example of doing a using clause which leverages this behavior.

Dec 19, 2012 at 10:07 PM
Edited Dec 19, 2012 at 10:09 PM

I agree that it's a bit cumbersome to have to prefix things pulled from an "internal module" with their namespace but what I've found is that you can easily simulate a "using" clause if you import stuff from your internal modules in much the same way you do with "external modules".

If you look at the example below you'll see that you can define a variable within a modules closure scope (the important part) that acts as an alias for anything defined within another module.  It's very similar to the "var http = require("http");" statement you would do to import an external module only you don't need the require() call.

This pattern has a couple of things going for it. 1) it means a lot less typing on your part as you don't need to namespace prefix everything. 2) it helps the minification process as a minifier will covert 'Foo' to 'a' or something throughout your code.

It's worth noting that this pattern won't work for interfaces (those are purely compile time constructs) or variables but importing classes, functions, & modules should work fine. 

module lib {
	// Define modules classes
	export class Foo {	}
}

module app {
	// Import other modules & classes
	var Foo = lib.Foo;
	
	// Define modules classes
	export class Bar {
		private foo = new Foo();
	}   
}

Dec 19, 2012 at 10:09 PM

As far as I can see, declaring variables at module scope doesn't allow you to do anything you couldn't do without them, which at least makes them non-essential.

And even if you can come up with some scenario in which they are useful, not having your generated JS consist of 25% "wrapper junk" would be a huge benefit in terms of debugging experience, code size/bandwidth usage, performance, etc.

For any general-purpose programming language, a feature that benefits most people most of the time is almost always preferable to a feature that only a few will use or benefit from. This is particularly true when the latter comes at the cost of not being able to do the former, which is what we have here.

All IMHO, of course :)

Dec 19, 2012 at 10:12 PM

As for the "using" import, I can see that being useful in some cases.. but imagine if all you had in C# was the alias-using clause, allowing you to import one type at a time. You'd have type-import-headers the size of Texas at the top of your files. I can't see myself going down that path.

Dec 20, 2012 at 12:00 AM
Edited Dec 20, 2012 at 12:02 AM

One of the goals of TypeScript is to stay as close to vanilla JavaScript as possible.  When you declare a module you are in fact creating a closure scope so while we can argue back and forth over the usefulness of that closure, doing anything to tamper with it seems like it would violate the goal of being standard JavaScript.  I just know from experience this would likely result in the occasional really odd bug. If you've ever had to track down an issue that a minifier introduced you'll know what I mean...

I personally like the ability to spread a modules definition across multiple files but there isn't an argument that says if you don't like all of the extra closures this results in you should just put all of your classes for a module in a single file. 

Another thing worth pointing out is that in a production environment you're likely minifying & combining all of these files and then delivering them to the client with gzip compression enabled.  The gzip compression will pretty much negate all of this duplication so in reality the result is just slightly more code for the browser to parse.  Modern JavaScript engines are so fast that this additionally parsing is essentially negligible.  I'd be really surprised if eliminating this duplication on even the largest projects resulted in >1ms faster load times. 

Dec 20, 2012 at 12:13 AM

A module is a TypeScript construct (as opposed to something JavaScript itself defines). As such, the language designers are free to specify what rules apply to it.

That it happens to compile to a closure scope is just the idiomatic way of encapsulating something in JavaScript, and therefore the natural way for the compiler to implement the module construct.

I do want my code to span across files. I find large files unmanageable and unproductive to work with, which is precisely why I so strongly believe that the current module implementation is poorly suited for managing large code bases (one of the goals of TypeScript, as I recall).

Modern JS engines may be fast but I'm targeting mobile devices, and most of those are pretty darn slow, so everything counts.

Dec 20, 2012 at 12:20 AM

Modules are actually a proposed ES6 construct so they should be in the next version of JavaScript.  TypeScript tries to be a superset of ES6 so in some places they're mercy of how ES6 is planned to work.

http://wiki.ecmascript.org/doku.php?id=harmony:modules_examples 

Dec 20, 2012 at 12:29 AM

That is true, but if TypeScript is not going to provide useful abstractions over plain JS then there isn't much point in using it.

Perhaps I should advocate for an "implicit" modifier to the module keyword instead. An opt-in mechanism that would allow me to change how the compiler treats a given module declaration (i.e. scoped/encapsulated or unscoped/merged).

Dec 20, 2012 at 12:51 AM

I should add that I would be all for something similar to "using". I was simply trying to show one way of achieving that today.  You may not have noticed but there are already places in TypeScript where you get this in an automatic way.

 

module a {
	export class Foo {}
}

module a.b {
	export class Bar {
		private foo = new Foo();
	}
}

Notice that I didn't have to type a.Foo() yet they added it for me in the generated output:

var a;
(function (a) {
    var Foo = (function () {
        function Foo() { }
        return Foo;
    })();
    a.Foo = Foo;    
})(a || (a = {}));
var a;
(function (a) {
    (function (b) {
        var Bar = (function () {
            function Bar() {
                this.foo = new a.Foo();
            }
            return Bar;
        })();
        b.Bar = Bar;        
    })(a.b || (a.b = {}));
    var b = a.b;
})(a || (a = {}));

 This only happens when a child namespace references a member of a parent namespace.  A "using" clause would be useful in making this magic happen anywhere.  

Dec 20, 2012 at 10:03 AM

I wasn't aware of that happening, but glad to see that it is already partially available.. and that I'm not alone in wishing it was more widely supported.

TypeScript is still young and some early-adopter pain points are to be expected, but hopefully this particular issue will be fixed.

Dec 20, 2012 at 10:32 AM

@ickman, yes we wouldn't want the compiler to try combining closures, because that might well bring the web to a grinding halt!

Here is a suggestion, based on how we used to organise our JS code in those dark days before TypeScript:

 

We declare the structure of the required namespaces in a separate file.

 

// Global namespace declaration file MyNamespaces.ts
namespace my { interfaces{}; classes{};  }

 

 

Each TypeScript class is declared in its own file.

 

// Bleeter.ts
module my.classes {
	var className = "my.Classes.Bleeter";
	export class Bleeter {}
}

// Greeter.ts
module my.classes {
	var className = "my.Classes.Greeter";	
	export class Greeter {	}   
}

 

 

The proposed JavaScript compilation of each file:

// MyNamespaces.js
var my = { interfaces: {}, classes: {} };

// Bleeter.js
(function(classes){
	var className = "my.Classes.Bleeter";
	classes.Bleeter = function Bleeter(){}

})(my.classes);

// Greeter.js
(function(classes){
	var className = "my.Classes.Greeter";
	classes.Greeter = function Greeter(){}
	
})(my.classes);

 

The basic improvement is that we inform TypeScript of our intended namespace structure, so that it can optimise away all the unnecessary guesswork, for example:  "my = my ||  {}" and so on.

There is only one minor consideration: The bundling mechanism must ensure the namespace file is included before any other file.

Noel

Dec 20, 2012 at 11:53 AM

@Noel that would work for me too.

The key thing I want to avoid is having module prefixes everywhere a given type is used, littered throughout the code base. Having a single file somewhere that avoids this, even if it is something I have to create and maintain manually, would be a huge benefit.

Dec 21, 2012 at 10:32 AM
Edited Dec 21, 2012 at 11:35 AM

I would personally say that the example of class name is really poor, who would put that in the outer scope of the class by design?...

Anyways, while modules are proposed in ECMA 6, I believe that "/// <reference path="...">" is a pure TS construct, so when we define how that works, that doesn't have much to do with ECMA it self... 

The question is, would anyone really write modules like so in real JavaScript if they could avoid it???

It doesn't make allot of sense to me to do:

var my;
(function (my) {
    (function (classes) {
        var className = "my.Classes.Bleeter";
        var Bleeter = (function () {
            function Bleeter() { }
            Bleeter.prototype.name = function () {
                return className;
            };
            return Bleeter;
        })();
        classes.Bleeter = Bleeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));
var my;
(function (my) {
    (function (classes) {
        var className = "my.Classes.Greeter";
        var Greeter = (function () {
            function Greeter() { }
            Greeter.prototype.name = function () {
                return className;
            };
            return Greeter;
        })();
        classes.Greeter = Greeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;
})(my || (my = {}));

 

Except that it is my only way of separating my JS into multiple files. The scoping here actually becomes a problem for me, because what I actually wanted was:

 

var my;
(function (my) {
    (function (classes) {
        var moduleName = "my.classes";
        var Bleeter = (function () {
            function Bleeter() { }
            Bleeter.className = "my.classes.Bleeter";
            Bleeter.prototype.name = function () {
                return Bleeter.className;
            };
            return Bleeter;
        })();
        classes.Bleeter = Bleeter;        
        var Greeter = (function () {
            function Greeter() { }
            Greeter.className = "my.classes.Greeter";
            Greeter.prototype.name = function () {
                return Greeter.className;
            };
            return Greeter;
        })();
        classes.Greeter = Greeter;        
    })(my.classes || (my.classes = {}));
    var classes = my.classes;

})(my || (my = {}));

 

If I wanted closure scope to work as in the first example, I would also name them differently...

But maybe that's just me who considers the above to be crappy design.

Dec 21, 2012 at 8:07 PM

@jmelgaard +1 - it's my point exactly.

The only time when the first code block is what you want is when they are from two independent libraries (that happen to choose the same root module name). But it's *never* what you want if those are two classes that are part of the same library or app, because if it was, you could just choose different module names for them instead.

Dec 26, 2012 at 8:04 PM

As a C# developer, I've been recently playing with both Dart and Typescript.  What I've discovered is that Dart's 'part of' for libraries, seems much more elegant than Typescript's modules.

It took me days to figure out how to build a multi-file library in Typescript (and have it actually work), and only a few minutes in Dart. Dart's multi-file library packaging is simple and elegant compared to all of the weird contortions of the many facets of Typescript modules (ECMA.Next | CommonJS | AMD? Internal/External ... compiler flags ...).  Above all, none of that works very well unless you glue some external JS library on top of it, or manually plaster <script> tags all over the place.  Having no prior WEB development experience, all of this looks so contrived.

The process of moving to JavaScript from C#, is like moving from 'Word' to 'Notepad' and trying to get the same quality content-presentation ... yes you can (using markup) build a Word document in Notepad, but why would anyone want to?

Dart may become the new Silverlight and just may succeed because, unlike Microsoft, Google is showing it has the 'b#lls' to stick it out.  I just can't imagine how bad Anders must feel about leaving C# for this crap.

Dec 27, 2012 at 12:57 AM

TypeScript is currently designed to adhere as closely as possible to the official JavaScript standards, which puts quite a few limits on what the language designers can do.

Personally I think it is a monumentally unwise decision, given that what most people want is simply an abstraction layer (aka nicer programming language) that makes them as productive as possible, while allowing easy interaction with existing JS code. To me, JS is just the IL of the web browser. Give it a couple of years and I'm sure we'll see a "binary JS" standard..

As such, I agree much more with the Dart design philosophy (but back when I checked it out it looked like an ugly mix of C++ and Java; now it actually looks a lot more polished, or maybe all my JS/TS coding has made me camelCaseInsensitive).

The way I see it, Dart is the new Java (as it was perceived when launched), and Microsoft has only recently caught on to the fact. Anders' job is simply to close the gap and ensure that Google doesn't run off with all the web developers..

Jan 1, 2013 at 1:48 PM
Edited Jan 1, 2013 at 2:19 PM

@mertner

That is not necessarily true, I have read quite a sum of good reviews or comments towards TypeScript exactly because it tries to go as close to original JavaScript and ECMA 6 as it possibly can, ofc. this comes from all those with the mind "If you wan't to write JavaScript, learn JavaScript, not coffee script or Dart"... And there appears to be quite a few of those...

Dart is really only cool in Google Chrome where you can run it without transforming it it JavaScript first, and then that ends... and AFAIK no other browsers standing in line to implement a Dart engine. That is to bad, but there is also so many devises etc. that runs JavaScript as is, so it's not quite as easy as "it's just the browsers" either...

As i have seen others state: "If it's a abstraction layer on top of JavaScript you wan't... Then why not go with either Dart, CoffeeScript, Script# or something else?"

I think it's good that TypeScript tries a different approach, one that actually teaches us JavaScript along the way, I like that philosophy, and after all, there is plenty of the other kind as is, we didn't need another one.

That doesn't limit us to define a way to resolve this though, after all there is nothing in JavaScript it self that can collapse several files into a single code file, that is only prepossessing that can do that. That is pure tooling, and how that work is completely decoupled from JavaScript it self in my opinion...

So lets keep this discussion within that boundary, what can we do about this and still stick closely to the mindset of TypeScript and not derail it, because I don't think that will help the cause at all...


> When you declare a module you are in fact creating a closure scope so while we can argue back and forth over the usefulness of that closure, doing anything to tamper with it seems like it would violate the goal of being standard JavaScript.  I just know from experience this would likely result in the occasional really odd bug. If you've ever had to track down an issue that a minifier introduced you'll know what I mean...

I am not necessarily to fond of suggesting this, but ill do it anyways.

 

//File: Class1.ts
partial module mod { 
    class Class1 { }
}

//File: Class2.ts
partial module mod { 
    class Class2 { }
}

//File: Class3.ts
module mod { 
    class Class3 { }
}

Would give the following output (at least when we ask to merge the files):

 

var mod;
(function (mod) {
    var Class1 = (function () {
        function Class1() { }
        return Class1;
    })();    
    var Class2 = (function () {
        function Class2() { }
        return Class2;
    })();    
})(mod || (mod = {}));

var mod;
(function (mod) {
    var Class3 = (function () {
        function Class3() { }
        return Class3;
    })();    
})(mod || (mod = {}));

 

One thing that bugs me is that if "Class1.ts" and "Class2.ts" would be compiled separately to each of their own files, we get a different behavior... as well as the "partial" keyword that doesn't really have anything to do with ECMA6...

But at least this way it becomes very explicit that we wan't the content of "module" to be collapsed, while maintaining the ability to keep the scope as is for current implementations.

 

Jan 2, 2013 at 3:42 PM

@jmelgaard,

 

The idea of a "partial" modifer is an interesting suggestion. It would work for the case when the TypeScript compiler is used to process a single project. By this I mean, tsc.exe is passed a list of TypeScript files to process, which are then compiled in a single pass.

This is a special case of the general approach, where TypeScript files are separated into separate projects, and tsc.exe is run independently on each project. This is what normally happens when one has TypeScript files organised in separate projects in Visual Studio.

For the general case if Class1.ts is in one project and Class2.ts is in a separate project then their respective complied JavaScript output files can only be combined by a bundling (or linking) mechanism - in other words: it is outside the scope of the compiler.

This is why I suggested the namespace option above, which would work in this situation. Also the behaviour is the same if all files are in one project or compiled individually.

Noel

Jan 3, 2013 at 1:20 PM
Edited Jan 3, 2013 at 1:21 PM

@nabog

I don't see the 2 solutions to be mutually exclusive. And I don't see the as solving the exact same problem, the solutions overlap allot though...

Essentially I would like to be able to split this up in multiple files...

 

module mod {
    var modName = "mod"; 
    export class Class1 { 
      className = "Class1"; 
      public hello(){
        return modName + '.'+ this.className;
      }
    }

    export class Class2 {
      className = "Class2"; 
      public hello(){
        return modName + '.'+ this.className;
      }
    }
}

Problem is that JavaScript nor TypeScript allows me to as-is... Then I have to export the module variable to access it because suddenly we are outside the closure for the second class.

It implies allot of issues to collapse that though, as you mentioned ones you compile each file individually you "break" it... it is also not "obvious" that you would have "modName" var in one file and can access it in another...

A Complete alternative is that I can view logical segments of a large typescript file separately, so that I am not burdened with seeing all the code in the same module at the same time, and being able to collapse modules, classes etc is not enough, it is still allot of noise in my way of thinking.

Before ind pure JS, making some simple pre-processing that did this sort of stuff wasn't that difficult in pure JavaScript. you could essentially have something like:

//module.js
var mod;
(function (mod) {
    mod.modName = "mod";
      
    //@import '{...}/Class1.js'
    //@import '{...}/Class1.js'
})(mod || (mod = {}));

//Class1.js
    var Class1 = (function () {
        function Class1() {
            this.className = "Class1";
        }
        Class1.prototype.hello = function () {
            return mod.modName + '.' + this.className;
        };
        return Class1;
    })();
    mod.Class1 = Class1;

//Class2.js
    var Class2 = (function () {
        function Class2() {
            this.className = "Class2";
        }
        Class2.prototype.hello = function () {
            return mod.modName + '.' + this.className;
        };
        return Class2;
    })();
    mod.Class2 = Class2;   

 

 

Because it wouldn't be the wiser, mod could be a global variable... it wouldn't know... so it would be ok with it...

In TypeScript... the compiler is the wiser however... And that is a good thing for many parts... but for this particular little case... It annoys me...

Jun 7, 2013 at 11:39 PM
It seems like there is a general consensus that we want something to the effect of a using statement, but that using statements can cause collisions, which could be dangerous.

Might I recommend the code below should be valid. In that code, there are two modules (Alpha and Bravo) each with a unique class and one collision (ClassCharlie). The second module (Bravo) has a using statement for the first (Alpha).

With nothing else specified, the compiler would return an error when trying to use the collision export (new ClassCharlie()), saying that the call is ambiguous.

With the addition of a disambiguating statement (using ClassCharlieFromAlpha = Alpha.Charlie;), there is no longer an ambiguity, and the problem is resolved. It might also be wise to require a disambiguating statement for each collision, and continue to return errors for collisions, forcing the user to perform a complete disambiguation.

This solves the problem without the creation of extra local variables in the module, and without having to create a local variable for each module export you intend to use.

Just a thought.
module Alpha {
    export class ClassAlpha { }
    export class ClassCharlie { }
}

module Bravo {
    using Alpha;
    using ClassCharlieFromAlpha = Alpha.ClassCharlie; //Disambiguating 

    export class ClassBravo { }
    export class ClassCharlie { }

    //Alpha.ClassAlpha
    var alpha = new ClassAlpha(); 
    
    //Bravo.ClassBravo
    var bravo = new ClassBravo(); 

    //Alpha.ClassCharlie
    var alphaCharlie = new ClassCharlieFromAlpha();

    //Bravo.ClassCharlie
    var bravoCharlie = new ClassCharlie();
}
Renders as
var Alpha;
(function (Alpha) {
    var ClassAlpha = (function () {
        function ClassAlpha() {
        }
        return ClassAlpha;
    })();
    Alpha.ClassAlpha = ClassAlpha;
    var ClassCharlie = (function () {
        function ClassCharlie() {
        }
        return ClassCharlie;
    })();
    Alpha.ClassCharlie = ClassCharlie;
})(Alpha || (Alpha = {}));

var Bravo;
(function (Bravo) {
    var ClassBravo = (function () {
        function ClassBravo() {
        }
        return ClassBravo;
    })();
    Bravo.ClassBravo = ClassBravo;
    var ClassCharlie = (function () {
        function ClassCharlie() {
        }
        return ClassCharlie;
    })();
    Bravo.ClassCharlie = ClassCharlie;

    var alpha = new Alpha.ClassAlpha();
    var bravo = new Bravo.ClassBravo();
    var alphaCharlie = new Alpha.ClassCharlie();
    var bravoCharlie = new Bravo.ClassCharlie();
})(Bravo || (Bravo = {}));
Jun 8, 2013 at 4:43 PM
Edited Jun 10, 2013 at 12:10 AM
I strongly agree with @jmelgaard and would like to see something similar to the "partial" keyword that allows to combine modules from different files into a single closure.

I would personally prefer just to see a 'namespace' keyword which would clobber code in the same closure. How that fits into ECMA6, I don't know.

Organizing a large codebase with TypeScript still seems like a huge pain point.

Overall I really like the approach of TypeScript but using requirejs and separate independent modules isn't really helping,
Aug 19, 2013 at 5:24 AM
Edited Aug 19, 2013 at 5:26 AM
I gotta give my +1 here. Managing a huge collection of files into a project is horrible in JavaScript, at best painful in TypeScript, and butchered in Dart. Dart had a semi acceptable system around 9 months ago but went backwards since, at least in my opinion.

What I want:
  • namespaces that can be nested
  • classes inside namespace should be able to access their own fully qualified name as well as shortname
  • the glue to include another ts file from your ts file should come automatically without using 3rd party libs
  • optimally: the glue to add in a .js file with a .d.ts file should come automatically as well without requiring <script> or a lib
  • I don't care if the resulting compiled js code is one file or not as long as it behaves this way
Dart doesn't offer this, TypeScript doesn't offer this and JavaScript doesn't offer this as well without some serious crutching...

I do agree with the concern of others here in the thread though that this is critical for large scale apps and so should be on a high priority.
Aug 22, 2013 at 8:35 PM
I find it strange that no one has really stuck to the ES6 implications.

The real issue is, when ECMAScript 6 is a standard, your code:
module lib {
    // Define modules classes
    export class Foo {  }
}

module app {
    // Import other modules & classes
    var Foo = lib.Foo;
    
    // Define modules classes
    export class Bar {
        private foo = new Foo();
    }   
}
will render to javascript like this:
module lib {
    export class Foo {  }
}

module app {
    var Foo = lib.Foo;
    
    export class Bar {
        private foo = new Foo();
    }   
}
It's very forward thinking and have heard they are going to alter the internal implementations of ES6 within typescript as they move towards a standard, keeping as close as possible to the spec.

I don't think writing good ES5 is the point of the ES6 elements in typescript today. You can already use it to write clever ES5 applications. The ES6 elements are to help you get ready for the future.
Aug 22, 2013 at 8:56 PM
@tombmedia

That's a really good point, and does make me question whether we need a better system than what is already in place. TypeScript is not about building a new language, but rather adding type annotations to an old one.

But is there harm is providing syntactic sugar for hiding a module variable, and providing access implicitly?

In fact, TypeScript already provides this syntactic sugar. Consider this code:
module A {
    export var x;
}

module A.B {
    export var y = x;
}
Which compiles to
var A;
(function (A) {
    A.x;
})(A || (A = {}));

var A;
(function (A) {
    (function (B) {
        B.y = A.x;
    })(A.B || (A.B = {}));
    var B = A.B;
})(A || (A = {}));
When I write "var y = x", the TypeScript compiler is inferring that I mean "B.y = A.x".

Why not extend the ability to implicity call A to circumstances other than submodules of A?

Does that make sense?
Aug 29, 2013 at 2:18 PM
I met the exact problem when trying to migrate one of our javascript library to typescript. Basically I want (1) many classes in separate files while under one 'module' or namespace (2) compiled to one js file with one closure.

What should I do? My current workaround is, to avoid using typescript and stay with javascript.
Aug 30, 2013 at 5:15 AM
I wonder if we could omit module closures in the source files, then concatenate all files and wrap them in one single module closure before sending to the compiler.
It is surely not ideal and comes with limitations, but that might even keep IDE support functional (e.g. referencing other classes without module prefix).

It still feels wrong and something that the compiler could assist in, but before dropping TypeScript entirely it might be an acceptable hack.
Aug 30, 2013 at 3:04 PM
+1 for supporting partial modules like jmelgaard proposed, this is really required to make closures work correctly without exposing internals.

But the issue about compiling to multiple module declarations with repeated code, I'd say it is not an issue. The result in the runtime is the same, it is correct javascript and there is no measurable speed difference in parsing one vs another. It would be nice if it worked this could be improved, but not a requirement. Can be optimized in the future.
Sep 9, 2013 at 8:04 PM
Been away from TS for a month or so, so slightly late to the party in this thread but I would very much support the addition of the "partial module".
Sep 19, 2013 at 11:57 AM
DRubino wrote:
@tombmedia (...) When I write "var y = x", the TypeScript compiler is inferring that I mean "B.y = A.x".

Why not extend the ability to implicity call A to circumstances other than submodules of A?

Does that make sense?
Yes, we need the ability to use a class without prefixing with a module name. The situation today is terrible and make TypeScript very hard to use.

In my case, I have a big project that I don't want to code in pure JS. I sill think TS is a better alternate solution than Dart but we need to fix this issue before 1.0.

A "using" keyword would be neat.
Sep 19, 2013 at 1:12 PM
You can now do this:
module abra.cadabra.superc.ali.frag.ilistic {
    export class Foo{
        f = "foo";
        doFoo(){
            alert(this.f);
        }
    }
}

module bar {
    import z = abra.cadabra.superc.ali.frag.ilistic;
    import Z = abra.cadabra.superc.ali.frag.ilistic.Foo;
    
    var fooOne = new z.Foo();
    var fooTwo = new Z();
    
    fooOne.doFoo();
    fooTwo.doFoo();
}
Sep 20, 2013 at 5:14 AM
@nabog

Yes you can import modules or single classes. Often, modules will contain a number of classes and it's not practical each one. Therefore, you have to import the module itself, using some sort of shorthand (in your example z). Now the codebase has multiple conventions for naming modules, one of which is rather cryptic.

I think using statements and aliasing would provide a more elegant solution to module name reduction, and would be elegant, in the sense that it provides an extension of module inference that is equivalent to the way it is done in sub-modules (see my comment above).

The more I code in TypeScript, the more I feel that using statements are a must have, and that importing at the module level adds an unnecessary amount of boilerplate to my code:

var thing = c.DoSomething(new c.NewThing());
var nextThing = new d.OtherThing(thing);

The code is littered with c. and d., which provide little semantic value, and decrease the readability of the code. To import class by class, I need to add a lot of boiler plate to achieve the desired effect of a using statement, and in a way that doesn't scale well with the number of classes used:

import DoSomething = Charlie.DoSomething;
import OtherThing = Delta.OtherThing;

For me, it's a must-have feature.
Sep 27, 2013 at 1:33 PM
Well, the import z = .... does not help a lot.
As DRubino said, the source code looks like a constellation of "z.", "d.", "c.", etc and all those prefixes are meaningless.

From my point of view, we realy need a solution to fix this issue ASP.
Sep 29, 2013 at 11:35 AM
@DRubino/@dcrespe, the import simply creates an alias for a namespace and is useful when dealing with a namspace structure with a deep hierarchy.
(In fact the import statement isn't really necessary: a var can be declared directly instead.)

So, yes, I agree that we need the using keyword for importing a namespace into a specific file.
Sep 30, 2013 at 3:19 PM
What does the TypeScript team think about the discussion so far? There are some good points here..
Sep 30, 2013 at 3:50 PM
I second feedback from the TypeScript team! This feels like an important issue to a number of developers.
Sep 30, 2013 at 5:59 PM
I don't usually like to post when I have nothing to contribute except agreeing, but I totally agree with this discussion. Having the same module look the same across the codebase is a big readability issue.
Oct 6, 2013 at 2:08 PM
DRubino wrote:
I second feedback from the TypeScript team! This feels like an important issue to a number of developers.
Is there any technical issues that would prevent the Typescript team from implementing a "using" feature ?
Coordinator
Oct 11, 2013 at 10:00 PM
Using "using" is very similar to JavaScript "with" statements, which create a block and it becomes fairly complex to reason about the scopes of symbol uses.

Our module system is planned to align as closely as possible with ECMAScript 6's module system, now that that's going into place. Last I looked into it (I haven't read the most recent stuff that's come out in the last couple days), there wasn't an "import * from bar" syntax that would pull all the exported symbols into the current namespace.

This is one of those design decisions that has a pretty divided opinion, so I suspect we'll err on the side of keeping with what ES6 recommends.

That said, once we do align, you should be able to pull out multiple symbols from the module as local names. While this wouldn't give you a wildcard, you would get a set of symbols that don't require full qualification.
Oct 13, 2013 at 7:30 AM
Thank you for your reply.

I have been programming with using statements for quite some time, and when backed by compiler that can detect ambiguity issues and a langauge that can resolve them, using statements only make life easier. It seems that the main difference between "using" and "with" is when they are evaluated. A "using" statement would be compile-time syntactic sugar for a reference to the module, in much the same way it works in submodules:
module A {
   export class AClass { };
}

module A.B {
    export var a = new AClass();
}
converts to:
var A;
(function (A) {
    var AClass = (function () {
        function AClass() {
        }
        return AClass;
    })();
    A.AClass = AClass;
    ;
})(A || (A = {}));

var A;
(function (A) {
    (function (B) {
        B.a = new A.AClass(); //AClass is generated as A.AClass. This is what a using statement could do.
    })(A.B || (A.B = {}));
    var B = A.B;
})(A || (A = {}));
It feels very restricting to have to add a class to a submodule of A just to get unqualified names for all of the exports in A. It would feel more natural to have using statements (or import wildcards), and have the compiler check for ambiguities. This still feels to me like a "must have" for application scale development, especially given that we have design-time type-checking.
Oct 30, 2013 at 1:28 PM
jonturner wrote:
This is one of those design decisions that has a pretty divided opinion, so I suspect we'll err on the side of keeping with what ES6 recommends.

That said, once we do align, you should be able to pull out multiple symbols from the module as local names. While this wouldn't give you a wildcard, you would get a set of symbols that don't require full qualification.
I don't know if the ECMA6 team really want to stick with very long class name such as "standard.structure.BinaryTree" but it is not manageable for serious projects.

The need of pointing every single classes we want to use as a local name can be tiedous too. It can lead to dozen of lines of code to declare what classes must be considered as local (a module may have hundreds of classes).

The compiler should do the work and identify the ambiguities. If ECMA6 does not include this feature, TypeScript must provide it as an extension of ECMA6.
Nov 5, 2013 at 2:47 AM
Edited Nov 5, 2013 at 2:48 AM
Guys, just trying to catch up from October of 2012 till now, apologies if this was already covered elsewhere. I'm still having the same problems with modules that I had a year ago with the latest source... is this still not fixed/modified/understood/acknowledged?

All I want to do is create custom types (Value Objects, Java POJO's, Domain Objects, whatever...) and have TypeScript ensure it's the correct type. So far, it works, but the syntax is still awful. Python, Ruby, Java, C#, and ActionScript 3 allow you to import a class, and then have that namespace be "defined" magically, and you just supply the class.

TypeScript however, requires me to use both the module local variable but also the entire package path. This is not going to work for large code bases and the CoffeeScript guys have ammo, which is horrible.

Observe:
export module com {
    export class Message {
        greeting: string;
        constructor(greeting: string) {
            this.greeting = greeting;
        }
        greet() {
            return "Hello, " + this.greeting;
        }
    }
}
And then I use that defined VO like so:
import MessageModule = module("com/Message")

module Sayings {
    export class Greeter {
        message: MessageModule.com.Message;
        constructor(message: MessageModule.com.Message) {
            this.message = message;
        }
        greet() {
            return "Hello, " + this.message.greet();
        }
    }
}

var Message = MessageModule.com.Message;
var message = new Message("world");
var greeter = new Sayings.Greeter(message);
Compiles great. Now if I modify the last line like so:
// var greeter = new Sayings.Greeter(message);
var greeter = new Sayings.Greeter("a string not a VO");
The tsc compiler correctly shows an error of "Supplied parameters do not match any signature of call target".

So, while I don't mind making references to the module in code, having to make full module + package paths for class variable types is awful.

Is this going to be improved/fixed?
Nov 6, 2013 at 3:07 PM
Edited Nov 6, 2013 at 4:44 PM
Took me a while but I just read this entire thread. If I may, allow me to add my thoughts: 2 points come to mind.

1. Modules and Closures

I created an issue and realise now that it was probably not the best place to put it.

I see no reason why module definitions spread across files should share the same closure. Currently, in JavaScript, if you want to share values you must attach it to a shared object. Such as, from constructors to functions on the prototype - if you want to share something, attach it to this.

As stated in the issue, I don't see why there must be several closures for one module definition with deep namespacing. As I see it, the arguments put forward, above, push for no closures or a shared closure among different files. As only trivial examples of 1- or 2-depth namespacing (ns1 or ns1.ns2) are used, I understand why I don't see an argument for one closure per module, but please consider having namespaces 4plus deep: your JS code can get pretty messy.

Considering you can't place code in between each level of namespacing (the dots), it's a little naive to consider the 2 examples, below, the same:
module ns1.ns2.ns3 {
    var x; // dummy code for playground to output
}

module ns1 {
    export module ns2 {
        export module ns3 {
            var x; // dummy code for playground to output
        }
    }
}
Notice how both will output the same javascript:
var ns1;
(function (ns1) {
    (function (ns2) {
        (function (ns3) {
            var x;
        })(ns2.ns3 || (ns2.ns3 = {}));
        var ns3 = ns2.ns3;
    })(ns1.ns2 || (ns1.ns2 = {}));
    var ns2 = ns1.ns2;
})(ns1 || (ns1 = {}));

var ns1;
(function (ns1) {
    (function (ns2) {
        (function (ns3) {
            var x;
        })(ns2.ns3 || (ns2.ns3 = {}));
        var ns3 = ns2.ns3;
    })(ns1.ns2 || (ns1.ns2 = {}));
    var ns2 = ns1.ns2;
})(ns1 || (ns1 = {}));
Apologies for the large set of code, but I guess it proves the point - and that's only 3 levels deep!

For my proposed solution, see the issue linked above.

2. Implicit Prefix of Imported Entities

Sorry for using "entities" there. Lack of a better word for modules/classes/enums/variables...

I like the argument that A.x is available as x in A.B which transpiles to A.x in the JS, as I too find myself having to explain this to people - it seems to be a hidden gem. Luckily I noticed it, but it got me hooked, and now I find myself creating nested modules purely for that syntactic sugar. In my rather large app for my startup, there are nested namespace levels which really belong a level up, for example:
module ram {}
module ram.app1 {}
module ram.app2 {}
// i then have
module ram.app1.bindings {}
module ram.app2.bindings {}
// rather than
module ram.bindings {}
Really, KnockoutJs bindings don't even need a module or closure, but I do it purely to get the implicit prefixing. So is TypeScript inspiring me to write better code? In this case, no - it's actually the opposite.

In some cases, I omit an extra namespace. For example, I put all my enums under module ram {} rather than in module ram.enums {} because it's a pain to type enums.X everywhere and using import e = enums; is just as bad as it just reduces the readability of my code.

As I was reading the thread I was dying to shout ES6's import * from ns1.ns2 as I've seen it presented by Kit Cambridge in his ES6 conference talks. Not many cites of ES6 syntax above, instead recommendations of using. But I see @JonTurner already looked into that and said it had "a divided opinion". I guess the:
import { x, y, z } from ns1.ns2
would offer a method of implicit prefixing (albeit long-winded in many cases). But couldn't TypeScript (assuming this isn't too far from ES6 syntax) offer import * from ns1.ns2 and convert the * to the curly brace syntax, depending on what we use in the module body?

Apologies for an extremely long post. Hopefully I contributed something useful.
Nov 6, 2013 at 3:35 PM
@ramideas is import * in the ES6 spec? Jon Turner said that he hadn't seen such a syntax. But if it is in the spec, I'm sure it would make it into TypeScript.

Im regards to the focus on using, my guess is that TypeScript appeals to .Net developers programming in C#, and we know the import constructs that are familiar to us. I'm sure we're all willing to take a syntax that is consistent with ES6 as long as it allows us to reference the classes in a module without explicitly naming the module or its alias.

Re: closure sharing in modules: This breaks encapsulation for me. And I'm not sure how it would be implemented. Do you have any ideas?
Nov 6, 2013 at 4:35 PM
Edited Nov 6, 2013 at 4:48 PM
I'm taking Jon Turner's word, as I don't see import * ... on http://wiki.ecmascript.org/doku.php?id=harmony:modules (but I see export * ...).

RE: sharing closures amongst modules - who are you trying to hide the variable from? If it is yourself, wouldn't exporting a variable with an underscore prefix warn you? If it is others who are using your module, I agree this may be a use-case of a shared closure.

But with classes, setting something as private isn't truly private. At runtime, everything has access to it. The only thing preventing it is TypeScript's compile time detection, which can be bypassed by casting the enclosing object to any before accessing a private field.

My problem with a shared closure is the compiler then becomes responsible for ordering dependencies. Consider the compilation of 3 files:
// file1.ts
module A {
    var _x; // private variable, only accessible within this modules closure
}
// file2.ts
module B {
    // depends on something declared in file1.ts
    // shouldn't have access to _x
}
// file3.ts
module A {
    // uses _x somewhere
    // depends on something declared in file2.ts
}
For the above declarations of module A to share the same closure they need to be reordered so they are together, but the dependencies prohibit that.

I'm not saying I've thought this through thoroughly but a, possibly hacky, solution could be to declare var _x as export private var _x which would tell the compiler this needs to be available across closures. The compiler could then create and export an object from the module (called __shared, for example) which would hold _x as a property. I mean, you could do this now:
// file1.ts
module A {
    export var __shared__ = {};
    shared._x = 0;
}
// file3.ts
module A {
    __shared._x++;
}
All the compiler would have to do is parse something like export private var _x = 0; as export var _shared = {}; _shared._x = 0; and implicitly assume the _shared. prefix where these variables are used. Obviously any subsequent export private var _y = 0; would only add to the object (_shared._y = 0;) rather than redeclare it - rather like the var _this = this; declaration. (Those are 'plus' signs in the code, they seem to get HTML-escaped...)

Like I said, it's hacky. The reason I theorised using export private var rather than var is because you don't want to unintentionally hold onto var'd objects preventing the GC from doing it's thing.

Side note: Notice how I'm giving suggestions of how the compiler can parse 'new' typescript as 'current' typescript? Is this helpful? (I ask anyone who knows anything about the compiler) In my head, it's like parsing .NET code to IL. It's always the same IL, so the output process can remain the same. It's just the input/parsing process that needs modification.
Mar 18 at 8:31 PM
Another vote for the addition of a "partial" directive for module declarations. If you define classes in single .ts files and compile all output to a single .js file they compile with a module per class when the intent is generally a single module of each name containing all its classes.
Mar 18 at 8:50 PM
I agree with @ramideas. I've had to split up modules to get code to compile in the right order:
//File1.ts
module A {
     export class AClass { }
}

//File2.ts
module B {
     export var aclass = new AClass();
     export class BClass { };
}

//File3.ts
module A {
     export var bclass =  new BClass();
}
There is no way to reorganize this code to collapse the two module A declarations, as they are ordered to each require the previous file. In general, it might be hard to detect situations like this, and it would definitely lead to unexpected situations where you can or cannot use private variables in a module. Better to leave them declared as is, even with the redundancy and lack of access.
Mar 18 at 8:53 PM
Edited Mar 18 at 8:58 PM
On another note, I am still dying for some form of import*. Nested modules already effectively perform an import each other:
module A {
    //Declares some classes functions and variables
}

module A.B {
    //Has unprefixed access to the classes, functions and variables in module A
}
Is it such a stretch to extend that to modules outside of the heirarchy?
module C {
     import* A;

     //Has unprefixed access to the classes functions and variables in module A.
}
This is a must have, whether or not it is supported in ES6. Having a compiler to detect the ambiguities at design time could be the difference between including or not including this feature in a language spec. There might therefore be good reason for ES6 and TypeScript to go in different directions.
Mar 20 at 10:33 AM
Edited Mar 20 at 10:40 AM
Interesting topic!

I have a general question regarding namespaces/modules. I couldn't yet come up with a solution to organize my code just the way I want, although I think it should be possible.
So this is what I'd love to have:
  • each class has it's own .ts file, some may be in nested folders
  • have a TS library "MyLib", which has some top level classes as well as nested ones (eg. "util/Helper.ts", "gui/Button.ts")
  • have a TS app "MyApp" that has it's own classes (eg. "App.ts", "view/Main.ts" but uses some classes from "MyLib"
  • whenever I build that results in one js file that includes all the classes that MyApp needs, but I don't need AMD really (currently I use require.js for JS dev but in the end I compile to one file anyway), so if "view/Main.ts" statically declares that it uses "gui/Button.ts" that will be included in the compiled single js file (even if view/Main.ts doesn't use it actually). But if there's a class in "MyLib" that's not needed by "MyApp" that shouldn't be included.
  • in an ideal world a class could list all it's dependencies on top of it's file, and somehow I could set the "path" of "MyLib" in the settings of "MyApp" (like "../libs/MyLib" so this way multiple app projects can use the same library without needing to copy-paste library files.
  • once that's set "view/Main.ts" could use the type "gui/Button.ts" either by :
    • importing "MyLib/gui/Button" and simply refering to "Button" as the type (if 2 Buttons are imported then it needs to refer to it like MyLib.gui.Button
    • or if that's not possible then like MyLib.gui.Button or gui.Button
  • ideally the compiled end result is a single js file that tsc can produce, but if it can only be done with module loading systems like require.js, common.js, or some other external tool that's still ok as long as I can set it up to do the work everytime I save (I use webstorm).
  • using JS libraries is not an issue, I can just include them as script tags in the html and use their d.ts files
As you can see all I really want is to be able to organize my code as I used to do it in Java, Actionscript, etc.
Are these realistic / achievable requirements today? If there are projects that use similar organizing you can just point me to their github page. Really appreciate any help!
Mar 20 at 6:58 PM
I seem to have one big issue with how namespaces/modules work now: I can't seem to use a ts library from a project in a way that I only have to specify the path of that library once.
In the above example structure, if I want to use MyLib/gui/Button.ts from MyApp/view/Main.ts I need to use a reference tag relative to MyApp/view/Main.ts. If I want to use it somewhere else I need to add a reference tag there again relative to that .ts file. The problem is, if I move the library, I have to manually rewrite all of these references by hand which can be very time consuming.

Is it not possible to configure the path of "MyLib" once for the project "MyApp" and then just reference "MyLib" as "MyLib", so either class inside MyApp can uniformly reference the Button.ts like this: "MyLib/gui/Button.ts". This way, if the path of MyLib changes, I can just edit the configuration for "MyApp" and everything else is good to go. This looks like something I'd need, but I can't I do it somehow with the current compiler?
https://typescript.codeplex.com/discussions/451757

On the other hand the reference tag is quite ugly, and I know it has a different purpose than using import, but this feels like a bit of a mess.

One solution I have currently is to generate a d.ts file for "MyLib" copy that to "MyApp/libs/MyLib.d.ts" and reference that. The problem with this is, if I just include the built MyLib.js as a script tag than the whole lib will be added, not just the classes that "MyApp" needs.
Mar 20 at 9:08 PM
@grizzly33 Excuse me if I am misunderstanding you, but the current TypeScript plugin for Visual Studio (and the previous one too, I believe) automatically include all TypeScript files in the project as references. If webstorm behaves differently, you may need to take it up with JetBrains.

This still doesn't solve the problem of references in other projects, but due to the nature of ASP.Net projects (and IIS, I believe), you can't actually include TypeScript files from other projects without copying the compiled JavaScript to a directory in the current project that is permissioned to serve files.

So in general, it feels like there is more work to be done to facillitate modularization and reuse.
Mar 20 at 10:05 PM
thanks for the answer! Well, so far I haven't used Visual Studio for web development, but I may give it a shot. I preferred WebStorm so far.
I understand that from an ASP.Net POV, but I think when it comes to TypeScript that context shouldn't come in discussions: I think we're on the wrong track if some feature of TypeScript is influenced by the nature of how .Net or Visual Studio works, especially if it conflicts the interest of many users (if that's the case).

Although, even if the library files need to be included in the project I think it would be very useful to configure a path name and be able to reference that path with it's name instead of using the path everywhere.
But generally I think it's a pretty common requirement to have only a single instance of a library during development. If I change a library I don't want to copy paste it to all projects again that use it. Or actually I may want that (in which case I just copy it), but I want the ability that I can use a single instance too, which I can achieve perfectly with require.js currently (I just hate the typeless nature of it..

Is this currently not possible? I'm thinking, if all else fails, it shouldn't be too hard to modify the compiler to handle this, but I don't like the idea to come up with something not standard.
Mar 20 at 11:08 PM
Edited Mar 20 at 11:08 PM
@grizzly33 I hear what you are saying about the config file, and I wouldn't be surprised if someone told me that this already exists for Visual Studio. I cannot speak for Webstorm.

It occurs to me that solutions of the form that we are exploring would be outside the realm of the TypeScript compiler. For instance, I don't think a config file that centralized the dependencies of a web project would actually be passed in to tsc.exe. It would instead influence the way the IDE makes use of the TypeScript compiler. Therefore we would need to talk about TypeScript support in our respective IDEs.

An analogous feature is TypeScript intellisense. That TypeScript as a language is designed to allow for static analysis is one thing, and should be discussed in a forum on language design. But the actual implementation of compile-time tooling is the responsibility of the IDE developers.

If anyone has a better grasp on the divison of responsibilities here, please let us know.

With regard to the language, I am pushing for a more robust import system. It is my belief that the TypeScript tooling to resolve ambiguities that arise from unprefixed class, function and variable importation would be relatively easy to implement. Or at least, they would not be more complex to implement than the many features of the wonderful tooling that already exists for TypeScript in Visual Studio and Webstorm.
Mar 21 at 12:13 AM
Well, yeah maybe it's not the language's responsibility, to be honest I can't see into that deep enough to judge yet.
For my use-case though, where I'd want to use libraries externally (without copy pasting them) what do you suggest is the best workflow? My only idea for now is to generate a d.ts file for the lib, and use that as a kind of a replacement for the config file in the app's classes where it's needed.
Mar 21 at 1:41 AM
@grizzly33 For that use case, I would recommend creating a console application which finds and compiles external files, and then generates 1) a single JavaScript file and 2) a definition file for all of them (d.ts). That program can take a destination for those files as an input, and can be run on build for your current project.

It may take a bit of extra work, but if you write the program in a sufficiently abstract way, it should be reusable for your future TypesScript projects. I use a similar strategy to handle external references for myself. I hope that helps!
Mar 21 at 8:47 PM
Edited Mar 21 at 8:47 PM
thanks, that sounds like a good approach. I hope to find the time to write it, in the meantime if someone already has something like that on github let me know!