Open-Source Wikis

/

TypeScript

/

Primitives

/

Symbol

microsoft/TypeScript

Symbol

The binder's record of a named declaration. A Symbol represents one thing that has a name in the program — a variable, function, class, interface, type alias, namespace, property, parameter, etc. — and tracks all its declarations.

Definition

In src/compiler/types.ts:

export interface Symbol {
  flags: SymbolFlags;
  escapedName: __String;
  declarations?: Declaration[];
  valueDeclaration?: Declaration;
  members?: SymbolTable;
  exports?: SymbolTable;
  globalExports?: SymbolTable;
  /* @internal */ id?: SymbolId;
  /* @internal */ mergeId?: number;
  /* @internal */ parent?: Symbol;
  /* @internal */ exportSymbol?: Symbol;
  /* @internal */ constEnumOnlyModule?: boolean;
  /* @internal */ isReferenced?: SymbolFlags;
  /* @internal */ lastAssignmentPos?: number;
  /* @internal */ assignmentDeclarations?: Map<number, Declaration>;
}

SymbolFlags

A bit-set covering every kind of declaration:

  • Value declarations: Variable, FunctionScopedVariable, BlockScopedVariable, Function, Class, EnumMember, Property, Method, Constructor, GetAccessor, SetAccessor.
  • Type declarations: Interface, TypeAlias, TypeParameter, TypeLiteral.
  • Module declarations: Module, ValueModule, NamespaceModule.
  • Other: Alias (import/export specifier), ExportValue, ExportType, ExportNamespace, Prototype, ObjectLiteral, Optional, Transient, Assignment, EnumMember.

Multiple bits are common — a Symbol for a class is Class | Value, an interface that merges with a class becomes Class | Interface | Value | Type, and so on.

__String

escapedName: __String is a branded string. The escape function escapeLeadingUnderscores doubles leading underscores (__foo___foo) so the name doesn't collide with reserved double-underscore properties on JavaScript objects (which used to be the implementation backing SymbolTable). Always use unescapeLeadingUnderscores before showing a name to a user.

SymbolTable

A Map<__String, Symbol>. Every container that owns names (SourceFile, function bodies, blocks, modules, classes, etc.) has one or more:

  • locals on the container — the value/type lookup scope.
  • members on a class/interface — instance/static members.
  • exports on a module — what the outside world can reach.

Symbol tables are mutable during binding but conceptually frozen once binding is done.

Merging

When two declarations of the same name appear in the same scope and TypeScript's merging rules allow it, the binder merges them into one Symbol:

  • An interface and a namespace merge — the result is callable as a value (the namespace) and usable as a type (the interface).
  • A class and an interface merge — the class can implement extra members declared by the interface.
  • Two namespaces in different files merge into a single global namespace.
  • An enum and a namespace merge.

Merging is what powers TypeScript's "declaration spaces" — the same name can mean different things in value vs. type position.

Look-up

The checker resolves names via resolveName(location, name, meaning, ...). meaning (a SymbolFlags mask) controls whether the lookup wants a value, a type, a namespace, or some combination. The walker climbs from location up through containers, asking each SymbolTable for a matching name with overlapping flags & meaning.

Symbol vs. Declaration vs. Type

Three related but distinct concepts:

Concept What Where
Declaration A syntax node (e.g., VariableDeclaration) parser output
Symbol The bound identity of a name binder output
Type The checker's view of a value checker output

A symbol can have many declarations (merged interfaces, function overloads, namespace fragments). A declaration has at most one symbol (node.symbol). A symbol has one type per access path (the symbol's declared type plus narrowed types at specific positions).

Integration points

  • Binder (binder.ts) creates and merges symbols.
  • Checker (checker.ts) is the primary consumer. Almost every check starts with getSymbolAtLocation(node) or resolveName(...).
  • Language service uses symbols for find-references, rename, completions.
  • Declaration emit uses symbols when synthesising .d.ts and references them by their canonical declaration.

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Symbol – TypeScript wiki | Factory