microsoft/TypeScript
Node
The fundamental unit of the AST. Every parsed token, expression, statement, and declaration is a Node tagged with a SyntaxKind.
Definition
The base interface lives in src/compiler/types.ts:
export interface Node extends ReadonlyTextRange {
readonly kind: SyntaxKind;
readonly flags: NodeFlags;
/* @internal */ modifierFlagsCache: ModifierFlags;
/* @internal */ readonly transformFlags: TransformFlags;
readonly decorators?: NodeArray<Decorator>;
readonly modifiers?: ModifiersArray;
/* @internal */ original?: Node;
/* @internal */ symbol: Symbol;
/* @internal */ locals?: SymbolTable;
/* @internal */ nextContainer?: Node;
/* @internal */ localSymbol?: Symbol;
/* @internal */ flowNode?: FlowNode;
/* @internal */ emitNode?: EmitNode;
/* @internal */ contextualType?: Type;
/* @internal */ inferenceContext?: InferenceContext;
parent: Node;
}SyntaxKind (also in types.ts) is a single enum that covers tokens, keywords, punctuation, and node kinds — with marker values like FirstToken, LastKeyword, FirstStatement to identify ranges.
Subtypes
Node is the base of a vast type hierarchy:
graph TD
Node --> Token
Node --> Declaration
Node --> Statement
Node --> Expression
Node --> TypeNode
Declaration --> NamedDeclaration
NamedDeclaration --> VariableDeclaration
NamedDeclaration --> ClassDeclaration
NamedDeclaration --> FunctionDeclaration
Statement --> Block
Statement --> IfStatement
Statement --> ForStatement
Expression --> CallExpression
Expression --> BinaryExpression
Expression --> Identifier
TypeNode --> TypeReferenceNode
TypeNode --> UnionTypeNode
TypeNode --> MappedTypeNodeEvery concrete node interface (e.g., IfStatement) lists its children as readonly properties. Nodes are created exclusively via src/compiler/factory/nodeFactory.ts.
Predicates
src/compiler/factory/nodeTests.ts ships type-narrowing predicates for every kind: isVariableDeclaration(n), isCallExpression(n), isClassDeclaration(n), etc. These are the canonical way to check a node's kind because they double as TypeScript type guards.
Position information
Node extends ReadonlyTextRange:
pos— start of leading trivia (whitespace, comments) for this node.end— end of node text.getStart(sourceFile, includeJsDoc?)— start of the actual token text (skipping trivia).
The leading-vs-token distinction matters because tools that show "go to definition" or insert text before a node need to honour comments and whitespace correctly.
Synthetic nodes (those created during a transform, not parsed from source) have pos === end === -1. The emitter knows to skip source-map entries for them.
parent pointers
Every node has a parent pointer, set up by the parser via setParentRecursive. Walks like find-references rely on it heavily. When a transformer creates a new tree, it must call setParentRecursive (or use factory methods that handle it automatically) before the result is consumed by the checker.
flags and modifierFlags
NodeFlags is a packed bit-set containing things like:
Let,Const,Using,AwaitUsing— for variable declarations.OptionalChain,ExportContext,ContainsThis.Ambient— declared in an ambient context.JSDoc,Synthesized— origin markers.ThisNodeHasError,HasAggregatedChildData— internal cache markers.
ModifierFlags (computed from the modifiers list) covers public/private/protected/readonly/static/abstract/async/override/etc.
Walking the tree
Two primitives:
forEachChild(node, cb, cbNodes?)— read-only walk; callscbfor each child.visitEachChild(node, visitor, context)— transforming walk; replaces children that the visitor changes.
These are defined in src/compiler/parser.ts and src/compiler/visitorPublic.ts respectively. Both have many corner cases (decorators, type parameters, JSDoc) baked in — never hand-roll a walker.
Memory and identity
Nodes are not flyweighted. Two parsed instances of 42 are two distinct NumericLiteral nodes. However, identity is preserved across update* factory calls when no children change — factory.updateBinaryExpression(node, ...) returns the original node if the new children are identical.
This is what makes incremental parses cheap: a transformer that walks the tree but doesn't change anything returns the original tree by reference.
See also
- systems/parser for production rules.
- systems/factory for construction.
- primitives/source-file for the root node specifically.
- primitives/symbol for what gets attached after binding.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.