Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespace keyword #2159

Closed
sophiajt opened this issue Feb 26, 2015 · 26 comments
Closed

Namespace keyword #2159

sophiajt opened this issue Feb 26, 2015 · 26 comments
Assignees
Labels
Committed The team has roadmapped this issue Suggestion An idea for TypeScript

Comments

@sophiajt
Copy link
Contributor

Now that we have ES6 modules in TypeScript, we should probably move towards a cleaner separation in the module types.

In truth, "internal modules" have been a bit of confusion for developers new to TypeScript. They're much closer to what most people would call a namespace.

Likewise, "external modules" in JS speak really just are modules now.

Let's move to a simpler explanation and have namespaces and modules be more separate. We'd still support the previous syntax, but this would mean introducing a new keyword called 'namespace' that was a bit easier to read and doesn't conflict with ES6 terminology.

Before:

module Math {
    export function add(x, y) { ... }
}

After:

namespace Math {
    export function add(x, y) { ... }
}
@danquirk danquirk added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Feb 27, 2015
@nycdotnet
Copy link

Is this a keyword change only? For example, would clodules still be supported? (clamespaces?)

@DanielRosenwasser
Copy link
Member

It's an additional keyword that does the same thing. To the best of my understanding from current discussions, module would be deprecated in favor of namespace.

"clamespaces", "funspaces", and other exciting possibilities of names are just a nice bonus. 😄

@NoelAbrahams
Copy link

I like this suggestion.

We could make this change more potent by accompanying it with the use keyword.

math.ts

namespace math {
    export function add(x, y) { ... }
}

foo.ts

/// <reference path='math.ts' />
var num = math.add(0, 1); // Error: Unknown reference 'math'


use namespace math;

var num = math.add(0, 1); // okay
var num = add(0, 1); // also okay

This shouldn't be a breaking change because the error is only raised when the namespace keyword is used to declare a "module".

At the moment we are forced to keep our namespaces relatively flat in order to avoid problems with accessing deeply nested types:

var foo = foo.bar.baz.bazooka.add(10,3);
@basarat
Copy link
Contributor

basarat commented Feb 27, 2015

I strongly support this. The number of times I've had to explain is insane. Thanks!

@Steve-Fenton
Copy link

👍

@mihailik
Copy link
Contributor

mihailik commented Mar 3, 2015

A crucial expectation for namespaces is to span multiple declarations.

namespace Colors {
  export var Red = 'red';
}

namespace Colors {
  export var Green = 'green';
}

Here both Red and Green are heavily implied to be in the same namespace, as opposed to the second one extending the first.

Obviously, in JS/TS namespaces/internal modules actually create closures instead, see arguing about it on issue #447. This closure (and potentially an actual behaviour logic) doesn't quite fit with what 'namespace' implies. 'Module' is actually better.

module Colors {

  console.log('some work here...');

  export var Red = 'red';
}

module Colors {

  console.log('some other work here...');

  export var Green = 'green';
}

However 'module' can become confusing after ES6 gains wider adoption. How about 'namespace module' instead?

namespace module Colors {

  console.log('some work here...');

  export var Red = 'red';
}

That way it looks clearer to me. It still is havily hinting towards 'namespace modules' having behaviour, not just scope. But at the same time it's also clear those are some special modules, not your normal ES6 modules.

@sophiajt
Copy link
Contributor Author

sophiajt commented Mar 3, 2015

@mihailik Not sure exactly what you mean. Multiple namespaces would let you span multiple declarations, just as internal modules do today. The codegen extends the existing module if it's there, rather than create a new closure each time. The linked issue seems to be more about the codegen being suboptimal in some cases.

Unlike modules, which are based around a file and aren't extendable, namespaces (nee internal modules) are extendable. The only caveat is that closed-over non-exported symbols can't be seen across each namespace being merged, but I'd argue that's a good thing rather than a bad thing.

@Steve-Fenton
Copy link

@jbondc external modules are called "Modules" in ECMAScript 6, so it makes sense to stick with calling them "Modules" in TypeScript.

@mihailik
Copy link
Contributor

mihailik commented Mar 3, 2015

@jonathandturner the question is not whether it's a good or bad thing -- the question is whether it's a naturally expected thing.

I'd say that 'namespace' suggests it's a syntactic construct, whereas 'module' suggests lifetime and behaviour.

@NoelAbrahams
Copy link

The objections to using namespace as the keyword seem rather academic from my point of view.

@nycdotnet
Copy link

"clamespaces", "funspaces", and other exciting possibilities of names are just a nice bonus.

I support this simply because of the possibility of funspaces.

@mihailik
Copy link
Contributor

mihailik commented Mar 4, 2015

Great summary, @jbondc !

To me keeping 'module', but adding a qualifier makes most sense: clearer English, and greater backward and forward compatibility. Few more:

scope module Colors {
  export var Red = 'red8';
}

closure module Colors {
  export var Red = 'red9';
}

extend module Colors {
  export var Red = 'red10';
}

Beware the familiarity of 'namespace' appealing to C#-aware folks! That's not a wise move to gain a wider foothold in JS universe.

@NoelAbrahams
Copy link

I'm not quite following the arguments. So we don't want to introduce a new keyword, and we don't want to do C#-aware stuff, but nobody complained about async/await?!

@mihailik
Copy link
Contributor

mihailik commented Mar 5, 2015

It's a fine line with C# and marketing. There's only so much of C# a layman JS developer is ready to take.

Say, German cars are fantastic. But if they come with German shops, German pedestrians and German road signs -- I'd have hard time adapting. Not ready to learn another language, me.

A bit of C# feels great. But sticking it everywhere, shoving it on the first line of every file -- that could feel just too foreign to a JS person.

@NoelAbrahams
Copy link

Makes perfect sense when the argument is couched in terms of Germans! 😄

I don't think it's absolutely correct to argue that since modules are emitted as JavaScript closures that one should call them that, because a closure is very much a JavaScript construct (read small code-base), and the code we write is more about managing related components spanning tens of thousands of LOC (for which JavaScript was not originally designed).

I would like to see namespace to have similar semantics as C#. We use a lot of internal modules and we use them as "namespaces" i.e. as a means of organising objects, defined across hundreds of files, into logical units. Consequently, unless this new keyword is accompanied by a using or similar construct, it will remain very much a cosmetic change.

I don't really care much about what the keyword is called (so long as it keeps the Germans happy!)

@fletchsod-developer
Copy link

"namespace" is the right way to go. It's not just about C#, but JAVA and other languages too using that concept. Javascript is the only thing, I know of, that use module. I noticed people everywhere are moving toward higher level language that write Javascript for us so we don't have to know of more dirty, more lengthy & more complicated scripts. C# use "using", JAVA use "import", other language use "??" etc. that we don't have to write declaration stuff.

@vvakame
Copy link
Contributor

vvakame commented Mar 9, 2015

👍
I saw any person who is confused by internal modules and external module.

@mihailik
Copy link
Contributor

mihailik commented Mar 9, 2015

OK, but Java does not have a namespace keyword in the first place.

The crucial problem with using 'namespace' is that it already HAS a very specific meaning in languages like C# and C++. It specifically is a name space, a space for names. It's a naming/addressing thing -- not a behaviour thing.

Internal modules in TypeScript are emphatically not merely a naming tweak. Fundamentally those modules have lifetime and behaviour. Those are not just bolted-on aspects, the lifetime and behaviour of modules need to be actively managed. They cause their share of bugs, sometimes require careful re-ordering or renaming to ensure initialisers are executed correctly.

The difference between TS 'internal module' and C# 'namespace' is like a difference between Class and Record in Turbo Pascal, if you know what I mean ;-)

It does make sense to have a separate word for 'internal modules', but not necessarily a first borrowed idea from C# is the right one.

@fletchsod-developer
Copy link

I dont see in my comment that I say JAVA do have "namespace" keyword. Just saying it in layman term for programmers that understand the concept of it.

@NoelAbrahams
Copy link

@jbondc,

If you would like the emit for namespaces to be different then that's just another suggestion. It doesn't really say anything about the need for wanting to have namespaces in TypeScript.

@mihailik
Copy link
Contributor

mihailik commented Mar 9, 2015

As long as the project overlords at Microsoft are content with the existing TS adoption, reusing the C# 'namespace' keyword is the reasonable way to go. Conquering the minds of the JS folk is not necessarily the goal, right? ;-)

@yahiko00
Copy link

yahiko00 commented Apr 7, 2015

I've read this interesting discussion. Both clever arguments on both side.
My opinion is the word "module" should stick to ES6 definition since TS has to be an ES6 superset.
And internal modules should be named in another way. The word "namespace" would be the most natural choice.

@robertpenner
Copy link

It seems many agree that "external/internal modules" is now sub-optimal language and often confusing to explain. I would add that it's also confusing while coding, because the words module, import and export are overloaded. They function differently depending on which type of module you're coding.

While I was learning TypeScript modules, I was initially under the impression that I could write an internal module, then simply add a compiler flag to magically produce an external module. It took time to realize things like:

  • External modules should not contain a namespace (which is practically the raison d'être of internal modules).
  • External modules do not contain the word module.
  • The meaning and rules for export are different depending on the context.
  • It's very difficult to have one source file be usable as both a namespaced library (for browser) and an external module (for Node). I'm still trying to figure out a simple solution.

Overall, TypeScript's module terminology meant that, once I was comfortable with internal modules and started to create external modules, I had to "unlearn" assumptions I had made.

@robertpenner
Copy link

Re: the "namespace and C#" concern, I say this with love: the world does not revolve around C#.
Should we not use the term class because it's so differently implemented in JavaScript?

@robertpenner
Copy link

namespace or package are the two best terms so far. It just so happens that both were clearly defined in ECMAScript 4.
[/me pours one out for ES4]

In ES4, package was the equivalent to a TypeScript internal module (though TS is more flexible).
An ES4 namespace was orthogonal to a package, and completely different from a C# namespace.

http://www.ecma-international.org/activities/Languages/Language%20overview.pdf

Package definitions are global definitions, qualified by namespaces.
class, function, and var bindings in the package can be qualified by either an ordinary namespace value or one of the special namespaces internal and public, which are just aliases for the package-internal and package-public namespaces.

package org.ecmascript.experiment {
    internal var v;
}
...
package org.ecmascript.experiment {
    public function f(k) { v += k; return v-1 }
}

ES4 namespaces always seemed a bit esoteric. I'd say few AS3/Tamarin developers ever made their own namespaces, whereas everyone created packages.

Explanations of ES4 namespaces:
http://blog.gskinner.com/archives/2010/01/a_complete_guid.html
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/namespaces.html

That being said, ES4's definitions of package and namespace have no moral claim on us today. What have the dead to do with the living?

@ahejlsberg ahejlsberg self-assigned this Apr 27, 2015
@ahejlsberg ahejlsberg mentioned this issue Apr 27, 2015
@ahejlsberg
Copy link
Member

Closed in #2923.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Committed The team has roadmapped this issue Suggestion An idea for TypeScript