Merging Namespaces
Similarly to interfaces, namespaces of the same name will also merge their members. Since namespaces create both a namespace and a value, we need to understand how both merge.
To merge the namespaces, type definitions from exported interfaces declared in each namespace are themselves merged, forming a single namespace with merged interface definitions inside.
To merge the namespace value, at each declaration site, if a namespace already exists with the given name, it is further extended by taking the existing namespace and adding the exported members of the second namespace to the first.
The declaration merge of Animals
in this example:
namespace Animals { export class Zebra { } } namespace Animals { export interface Legged { numberOfLegs: number; } export class Dog { } }
is equivalent to:
namespace Animals { export interface Legged { numberOfLegs: number; } export class Zebra { } export class Dog { } }
This model of namespace merging is a helpful starting place, but we also need to understand what happens with non-exported members. Non-exported members are only visible in the original (un-merged) namespace. This means that after merging, merged members that came from other declarations cannot see non-exported members.
We can see this more clearly in this example:
namespace Animal { let haveMuscles = true; export function animalsHaveMuscles() { return haveMuscles; } } namespace Animal { export function doAnimalsHaveMuscles() { return haveMuscles; // <-- error, haveMuscles is not visible here } }
Because haveMuscles
is not exported, only the animalsHaveMuscles
function that shares the same un-merged namespace can see the symbol. The doAnimalsHaveMuscles
function, even though it’s part of the merged Animal
namespace can not see this un-exported member.
Please login to continue.