2.4 Scopes

The scope of a name is the region of program text within which it is possible to refer to the entity declared by that name without qualification of the name. The scope of a name depends on the context in which the name is declared. The contexts are listed below in order from outermost to innermost:

  • The scope of a name declared in the global namespace is the entire program text.
  • The scope of a name declared in a module is the source file of that module.
  • The scope of an exported name declared within a namespace declaration is the body of that namespace declaration and every namespace declaration with the same root and the same qualified name relative to that root.
  • The scope of a non-exported name declared within a namespace declaration is the body of that namespace declaration.
  • The scope of a type parameter name declared in a class or interface declaration is that entire declaration, including constraints, extends clause, implements clause, and declaration body, but not including static member declarations.
  • The scope of a type parameter name declared in a type alias declaration is that entire type alias declaration.
  • The scope of a member name declared in an enum declaration is the body of that declaration and every enum declaration with the same root and the same qualified name relative to that root.
  • The scope of a type parameter name declared in a call or construct signature is that entire signature declaration, including constraints, parameter list, and return type. If the signature is part of a function implementation, the scope includes the function body.
  • The scope of a parameter name declared in a call or construct signature is the remainder of the signature declaration. If the signature is part of a function-like declaration with a body (including a function declaration, constructor declaration, member function declaration, member accessor declaration, function expression, or arrow function), the scope includes the body of that function-like declaration.
  • The scope of a local var or function name declared anywhere in the body of a function-like declaration is the body of that function-like declaration.
  • The scope of a local let, const, class, interface, type alias, or enum declaration declared immediately within the body of a function-like declaration is the body of that function-like declaration.
  • The scope of a local let, const, class, interface, type alias, or enum declaration declared immediately within a statement block is the body of that statement block.

Scopes may overlap, for example through nesting of namespaces and functions. When the scopes of two names overlap, the name with the innermost declaration takes precedence and access to the outer name is either not possible or only possible by qualification.

When an identifier is resolved as a PrimaryExpression (section 4.3), only names in scope with a value meaning are considered and other names are ignored.

When an identifier is resolved as a TypeName (section 3.8.2), only names in scope with a type meaning are considered and other names are ignored.

When an identifier is resolved as a NamespaceName (section 3.8.2), only names in scope with a namespace meaning are considered and other names are ignored.

TODO: Include specific rules for alias resolution.

Note that class and interface members are never directly in scope—they can only be accessed by applying the dot (‘.’) operator to a class or interface instance. This even includes members of the current instance in a constructor or member function, which are accessed by applying the dot operator to this.

As the rules above imply, locally declared entities in a namespace are closer in scope than exported entities declared in other namespace declarations for the same namespace. For example:

  1. var x = 1;
  2. namespace M {
  3. export var x = 2;
  4. console.log(x); // 2
  5. }
  6. namespace M {
  7. console.log(x); // 2
  8. }
  9. namespace M {
  10. var x = 3;
  11. console.log(x); // 3
  12. }