10.1 Namespace Declarations
A namespace declaration introduces a name with a namespace meaning and, in the case of an instantiated namespace, a value meaning in the containing declaration space.
NamespaceDeclaration: namespace
IdentifierPath {
NamespaceBody }
IdentifierPath: BindingIdentifier IdentifierPath .
BindingIdentifier
Namespaces are declared using the namespace
keyword, but for backward compatibility of earlier versions of TypeScript a module
keyword can also be used.
Namespaces are either instantiated or non-instantiated. A non-instantiated namespace is a namespace containing only interface types, type aliases, and other non-instantiated namespace. An instantiated namespace is a namespace that doesn’t meet this definition. In intuitive terms, an instantiated namespace is one for which a namespace instance is created, whereas a non-instantiated namespace is one for which no code is generated.
When a namespace identifier is referenced as a NamespaceName (section 3.8.2) it denotes a container of namespace and type names, and when a namespace identifier is referenced as a PrimaryExpression (section 4.3) it denotes the singleton namespace instance. For example:
namespace M {
export interface P { x: number; y: number; }
export var a = 1;
}
var p: M.P; // M used as NamespaceName
var m = M; // M used as PrimaryExpression
var x1 = M.a; // M used as PrimaryExpression
var x2 = m.a; // Same as M.a
var q: m.P; // Error
Above, when ‘M’ is used as a PrimaryExpression it denotes an object instance with a single member ‘a’ and when ‘M’ is used as a NamespaceName it denotes a container with a single type member ‘P’. The final line in the example is an error because ‘m’ is a variable which cannot be referenced in a type name.
If the declaration of ‘M’ above had excluded the exported variable ‘a’, ‘M’ would be a non-instantiated namespace and it would be an error to reference ‘M’ as a PrimaryExpression.
A namespace declaration that specifies an IdentifierPath with more than one identifier is equivalent to a series of nested single-identifier namespace declarations where all but the outermost are automatically exported. For example:
namespace A.B.C {
export var x = 1;
}
corresponds to
namespace A {
export namespace B {
export namespace C {
export var x = 1;
}
}
}
The hierarchy formed by namespace and named type names partially mirrors that formed by namespace instances and members. The example
namespace A {
export namespace B {
export class C { }
}
}
introduces a named type with the qualified name ‘A.B.C’ and also introduces a constructor function that can be accessed using the expression ‘A.B.C’. Thus, in the example
var c: A.B.C = new A.B.C();
the two occurrences of ‘A.B.C’ in fact refer to different entities. It is the context of the occurrences that determines whether ‘A.B.C’ is processed as a type name or an expression.