How imports should be treated

Topics: Language Specification
Dec 6, 2013 at 4:02 PM
About import declarations, spec 10.3:
An EntityName consisting of a single identifier... The resulting local alias references the given internal module and is itself classified as an internal module.
An EntityName consisting of more than one identifier... The resulting local alias has all the meanings and classifications of the referenced entity or entities. (As many as three distinct meanings are possible for an entity name—namespace, type, and member.) In effect, it is as if the imported entity or entities were declared locally with the local alias name.
Spec doesn't make it clear if "three distinct meanings" are used simultaneously or depending on the type of imported entity (for example, is module instantiated or not). I tried to check it using "duplicate identifier" test and failed miserably. Neither example 1, nor example 2 gives me any error about duplicating identifiers. Is this some kind of bug? How imported aliases should be treated?

Example 1
module M {
  export interface I {}
  export var F;

// var M: number; would indeed trigger an error
import m = M; // or M.F - no error
var m: number;
interface m {}
Example 2
module M {
  export interface I { }

import m = M; // or M.I
var m: number;
interface m {}
Dec 6, 2013 at 5:43 PM
One way to think of it:

The three distinct meanings are three separate places the same name can be used. A name can be a namespace, a type, and a value/member and any combination of the three.

Namespaces can be used to qualify names, like so:
var x: A.B.C;
Where A and B represent namespaces.

Types, of course, are just types, like the interface I below:
interface I {
  x: number;
  y: number;
and values/member, like 'x' below:
var x = 3;
x + 1;
Some declarations, like class C actually create entries for 'C' as both a type and as a value (for the constructor function). Modules create a namespace and a value.

The 'import' keyword lets you access all three places the name can be, and bring the definitions into scope. Taking a simple example:
module SimpleMod {
    export interface Point {
        x: number;
        y: number;
    export var Origin: Point = {x: 0, y: 0};

var smVar = SimpleMod;

import smImport = SimpleMod;

var x: smVar.Point;
var y: smImport.Point;
You'll notice there's an error when using smVar.Point. The reason is that the 'import' is pulling in the namespace and type information related to the name 'SimpleMod', whereas using just 'var' will access only the value side.

It's a little subtle, and takes a little playing with. Once this is clear, how other parts of the system work, including export=, will also be clear.
Dec 7, 2013 at 10:13 AM
Thanks, I understand everything. But why no error about duplicate identifier?