TypeScript import and namespaces

Topics: Language Specification
Dec 15, 2012 at 10:30 PM
Edited Dec 15, 2012 at 10:36 PM

Part #1 (based on my knowledge of Java/ActionScript/C# and what I see in TypeScript):

There are 2 two ways in order to specify namespace:

How it occurs in Java/ActionScript:
there is "source root" path and all namespaces should be same as path to file relative to "source root" path.
I.e. if "source root" is C:\project\src and some source file at C:\project\src\view\maps\MyMapView.java then it should to have "view.maps.MyMapView" namespace

How it occurs in C#:
namespace not depends from file path

How it occurs in TypeScript
Now I see triple standard in order to specify/use namespace:
*) if to use

import myModule = module("relativePathToTypeScriptFile");

then there are two ways for namespaces declaration:

1) single TypeScript file contains definition of single class without module declaration like:

// "src/view/MyClass.ts" file
export class MyClass {
    constructor(){
        // Do something
    }
}


in result when if this class will be imported into src/App.ts like

// "src/App.ts" file
import myClassModule = module("./view/MyClass");

export class App {
    constructor(){
        var myClassModule.MyClass = new myClassModule.MyClass();
        // Do something
    }
}


this "MyClass" class will have "view" namespace in this context. In other TypeScript file, which
located in other file path, "MyClass" will have other namespace.

In this case namespace depends from file path.

(The fact that "myClassModule" is superfluous already written here so I'll not repeat it)

2) single TypeScript file contains definition of module with inner class(es) declaration:

// "src/view/ViewModule.ts" file
export module View {
    export class MyClass {
        constructor(){
            // Do something
        }
    }
}


in result when if this class will be imported into src/App.ts like

// "src/App.ts" file
import viewModule = module("./view/ViewModule");

export class App {
    constructor(){
        var viewModule.View.MyClass = new viewModule.View.MyClass();
        // Do something
    }
}


In this case namespace depends from file path and from module declaration in TypeScript file.

*) if to use /// <reference path="pathToTypeScriptFile" />
then namespace depends from module declaration in TypeScript file

In result we have:
*) If single TypeScript file contains "single class/entity", import files using "import moduleName = module('...');" and compile as AMD modules then we have something like Java/ActionScript namespaces scheme.
*) If single TypeScript file contains module declaration and include TypeScript files using /// <reference ... /> and compile it as CommonJS modules then we have C# namespace scheme. And this is single case when compiller "--out" flag work in correct way.
*) third case is combined version (if use "single TypeScript file contains module declaration" and use file importing) when entity namespace depends from module declaration and from file path

In my opinion it is too much and this leads to confusion. In my opinion there should be single way for importing something into current source file. And there should be single standard for namespace declaration.

Because there are 3 compiler targets:
*) AMD modules
*) CommonJS modules
*) namespaces declared in global namespace (and included with help /// <reference ... />)

I would prefer to have hidden implementation of how something will be imported:
I'm just write

import something

 

and set appropriate flag for compiler.

Part #2

I can mistaken, but I'm think that most part of developers who use or want to use TypeScript come from static typed languages like Java, ActionScript, C# and so on.
In my opinion, Python, Ruby developers choose CoffeeScript just because it is closer for their languages.

All listed languages have term "namespace".

If I have

// View1.cs
namespace View
{
    class View1
    {
       
    }
}

// View2.cs
namespace View
{
    class View2
    {
       
    }
}


then in

// App.cs
using View;
class App
{
    View1 view1 = new View1();
    View2 view2 = new View2();
}


I'm not need to import each file from this namespace.

And if I have

// src/view/View1.java
package view;
public class View1
{

}

// src/view/View2.java
package view;
public class View2
{

}


then in

// src/App.java
import view.*;
public class App
{
    View1 view1 = new View1();
    View2 view2 = new View2();
}


I'm not need to import each file from this namespace too.

TypeScript require to import each file.

For Java / ActionScript / C# developers so habitually just write

using View;


or

import view.*;


and not care where classes of this namespace was declared - in single module or in several files.

Similar feature in TypeScript will make life easier.

May 7, 2013 at 8:24 AM
Please add the feature mentioned in Part #2. Besides Generics this is the most needed feature for "application scale" development, because an application scale app will have lots of files and it is impractical to import all the needed files in every file.
May 7, 2013 at 9:00 AM
May 8, 2013 at 1:48 AM
I just discovered today that you can't compile commonjs files into one nice big file to be required later, I think a more abstract approach like what is being suggested with #2 would solve this problem.

Example, a project indevelopment:
project
 |- File 1
 |- File 2
 |- File 3
 |- Folder 1
 |  |- File 4
 |  |- File 5
Becomes (for the end user):
project
If in each of those files I could say that they were part of the "project" package, then the compiler could output them to a single file when a particular compiler flag was set.

That way those who want to use the project simply import it as project (one file).

Another thing this would help immensely, which there is currently no/little support for is creating a .d.ts file for concatenated output of commonjs modules.

Also, .d.ts files that specify the package should have their corresponding javascript files concatenated into the file (only if the javascript file is in the same location as the .d.ts file and shares the same name).