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
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:
localson the container — the value/type lookup scope.memberson a class/interface — instance/static members.exportson 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
interfaceand anamespacemerge — the result is callable as a value (the namespace) and usable as a type (the interface). - A
classand aninterfacemerge — the class can implement extra members declared by the interface. - Two namespaces in different files merge into a single global namespace.
- An
enumand anamespacemerge.
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 withgetSymbolAtLocation(node)orresolveName(...). - Language service uses symbols for find-references, rename, completions.
- Declaration emit uses symbols when synthesising
.d.tsand references them by their canonical declaration.
See also
- systems/binder — symbol creation and merging.
- systems/checker — symbol consumption.
- primitives/type — the per-symbol type computation.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.