镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Namespace keyword #2159

Description

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) { ... }
}

Activity

  1. nycdotnet commented on Feb 27, 2015

    @nycdotnet

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

  2. DanielRosenwasser commented on Feb 27, 2015

    @DanielRosenwasser
    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. 😄

  3. NoelAbrahams commented on Feb 27, 2015

    @NoelAbrahams

    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);
  4. basarat commented on Feb 27, 2015

    @basarat
    Contributor

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

  5. Steve-Fenton commented on Feb 27, 2015

    @Steve-Fenton

    👍

  6. mihailik commented on Mar 3, 2015

    @mihailik
    Contributor

    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.

  7. sophiajt commented on Mar 3, 2015

    @sophiajt
    ContributorAuthor

    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.

  8. Steve-Fenton commented on Mar 3, 2015

    @Steve-Fenton

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

  9. mihailik commented on Mar 3, 2015

    @mihailik
    Contributor

    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.

  10. NoelAbrahams commented on Mar 4, 2015

    @NoelAbrahams

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

  11. nycdotnet commented on Mar 4, 2015

    @nycdotnet

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

    I support this simply because of the possibility of funspaces.

  12. mihailik commented on Mar 4, 2015

    @mihailik
    Contributor

    Great summary, Jon (@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.

  13. NoelAbrahams commented on Mar 4, 2015

    @NoelAbrahams

    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?!

  14. 4 remaining items

  15. mihailik commented on Mar 9, 2015

    @mihailik
    Contributor

    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.

  16. fletchsod-developer commented on Mar 9, 2015

    @fletchsod-developer

    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.

  17. NoelAbrahams commented on Mar 9, 2015

    @NoelAbrahams

    Jon (@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.

  18. mihailik commented on Mar 9, 2015

    @mihailik
    Contributor

    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? ;-)

  19. yahiko00 commented on Apr 7, 2015

    @yahiko00

    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.

  20. robertpenner commented on Apr 19, 2015

    @robertpenner

    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.

  21. robertpenner commented on Apr 19, 2015

    @robertpenner

    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?

  22. robertpenner commented on Apr 19, 2015

    @robertpenner

    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?

  23. ahejlsberg commented on Apr 29, 2015

    @ahejlsberg
    Member

    Closed in #2923.

  24. added a commit that references this issue on Aug 10, 2015
  25. locked and limited conversation to collaborators on Jun 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

CommittedThe team has roadmapped this issueSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions