microsoft/TypeScript
Architecture
The TypeScript compiler is a single-package, multi-entry-point TypeScript-on-Node application. Internally it is laid out as a strict layering: scanner → parser → binder → program/checker → transformers → emitter, plus a language service layer that wraps that pipeline for editor scenarios. Each layer is a TypeScript module under src/compiler/ (or src/services/ for the language service) and is exposed through a public namespace declared under src/compiler/_namespaces/ or src/services/_namespaces/.
Compilation pipeline
graph TD
subgraph Frontend
Sys["System host (sys.ts)"]
CLP["commandLineParser.ts"]
MR["moduleNameResolver.ts"]
Scanner["scanner.ts"]
Parser["parser.ts"]
Binder["binder.ts"]
end
subgraph "Type system"
Program["program.ts"]
Checker["checker.ts"]
Resolver["program → host\nresolutionCache.ts"]
end
subgraph Backend
Factory["factory/nodeFactory.ts"]
Transformer["transformer.ts + transformers/*"]
Emitter["emitter.ts"]
Sourcemap["sourcemap.ts"]
Decl["transformers/declarations.ts"]
end
Sys --> CLP --> Program
Sys --> Parser
Scanner --> Parser
Parser --> Binder
Binder --> Program
MR --> Program
Resolver --> Program
Program --> Checker
Checker --> Transformer
Factory --> Transformer
Transformer --> Emitter
Decl --> Emitter
Sourcemap --> EmitterFrontend
sys.ts— the abstraction over the host environment (Node, browser, watch APIs). Every part of the compiler calls throughts.sysso that hosts can be swapped (e.g., the language service substitutes its own).commandLineParser.ts— parsestsconfig.json,tscflags, and project references. The largest single piece of compiler configuration logic.scanner.ts— lexes UTF-16 text intoSyntaxKindtokens. JSX, JSDoc, and regular-expression sub-grammars are handled by the same scanner via mode flags.parser.ts— a recursive-descent parser that produces aSourceFileAST node. The parser is incremental: it caches and reuses unchanged subtrees when source text edits arrive.binder.ts— walks the AST and populatesSymboltables on each container node, computes flow nodes for control-flow analysis, classifies nodes as JS/TS-specific, and builds the per-source-file diagnostic stream.
Type system
program.ts— the central object that knows about the entire compilation: source files, references, options, the type checker, and the emit. Programs are immutable; watch mode produces a sequence of programs that share unchanged source files.moduleNameResolver.ts+resolutionCache.ts— implementnode,node16,nodenext,bundler,classic,node10module resolution and cache the results across program rebuilds.checker.ts— over 54,000 lines that implement type creation, assignability, inference, narrowing, control-flow analysis, contextual typing, and diagnostics. The checker is created lazily and answers questions on demand.
Backend
factory/nodeFactory.ts— the canonical builder for AST nodes used by the parser, transformers, and emitter. Every transform produces new nodes via this factory.transformer.ts+transformers/— a tree of transformer factories. Source files flow throughtransformTypeScript,transformClassFields,transformLegacyDecorators/transformESDecorators,transformJsx, and a--target-specific stack (transformES2015,transformES2017, …,transformES2022,transformESNext). A separatetransformDeclarationspipeline produces.d.tsoutput.emitter.ts— pretty-prints the transformed tree into.js,.d.ts, and source-map output. It also produces.tsbuildinfofiles for incremental compilation.
Public namespaces
The compiler does not use ESM-style import from inside its own modules at build time. Instead, every file imports from a generated namespace barrel under _namespaces/ (e.g., src/compiler/_namespaces/ts.js, src/services/_namespaces/ts.js). This is enforced by the local ESLint rule no-direct-import in scripts/eslint/rules/no-direct-import.cjs. The ts namespace is the public boundary surfaced by lib/typescript.d.ts.
Language service
The language service (src/services/) wraps the compiler in a host-driven, query-based API. Editors call getCompletionsAtPosition, findReferences, getQuickInfoAtPosition, etc. The service is purely synchronous; it relies on a LanguageServiceHost (provided by tsserver or by a custom embedding) to read files and snapshots.
tsserver (src/server/) is the over-the-wire protocol layer. It owns the project graph (editorServices.ts, project.ts), accepts JSON commands, and dispatches them to a LanguageService per project. See systems/language-service and systems/project-system.
Build system
hereby (a gulp-like task runner) drives builds via Herebyfile.mjs. Three artefact families exist:
built/local/— local build of the compiler used for development and tests.lib/— last-known-good (LKG) prebuilt compiler used to bootstrap.- Library
.d.tsfiles — copied fromsrc/lib/intobuilt/local/so the locally built compiler can type-check user code.
esbuild is used to bundle the compiler into single files (e.g., lib/typescript.js); a custom dtsBundler.mjs produces the public .d.ts bundle. See how-to-contribute/tooling.
Repository at a glance
| Area | Path | Lines |
|---|---|---|
| Compiler core | src/compiler/ |
~210k TS |
| Language service | src/services/ |
~70k TS |
tsserver |
src/server/ |
~25k TS |
| Standard library | src/lib/ |
~80k TS (mostly DOM .d.ts) |
| Test infrastructure | src/harness/ + src/testRunner/ |
~70k TS |
| Test cases | tests/cases/ |
~19k test files |
See by-the-numbers for more.
Cross-references
- systems/scanner, systems/parser, systems/binder, systems/checker, systems/transformers, systems/emitter describe each pipeline stage.
- primitives/node, primitives/symbol, primitives/type describe the foundational data structures.
- features/declaration-emit and features/modules cover cross-cutting features that span multiple subsystems.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.