This page documents the incremental compilation system and the multi-project solution builder in the TypeScript compiler. It covers how the compiler tracks file state across builds, determines which files are affected by a change, persists that state to .tsbuildinfo files, and coordinates builds across multiple projects linked by project references.
For details on the underlying Program object and compilation lifecycle, see Compiler Architecture and Program and Compilation. For details on the CLI tool, see tsbuild Command.
TypeScript exposes two related but distinct build acceleration mechanisms:
| Mechanism | Flag | Entry Point | Scope |
|---|---|---|---|
| Incremental compilation | --incremental | createIncrementalProgram | Single tsconfig.json |
| Solution builder | --build (tsc -b) | createSolutionBuilder | Multiple projects with references |
Both rely on the same underlying BuilderProgram abstraction and .tsbuildinfo persistence, but the solution builder adds a project-level dependency graph and up-to-date checking layer on top.
Incremental compilation wraps a normal Program with a BuilderProgram that tracks per-file content hashes and emits a .tsbuildinfo file. On the next invocation, it reads that file back and reuses unchanged files without re-type-checking them. src/compiler/watchPublic.ts141-153
The solution builder (SolutionBuilder) reads the references array from each tsconfig.json, performs a topological sort, checks each project's up-to-date status via UpToDateStatusType, and builds only the projects that are stale. src/compiler/tsbuild.ts10-38
Sources: src/compiler/builder.ts7-10 src/compiler/tsbuild.ts10-38 src/compiler/watchPublic.ts141-153
BuilderProgram is the public interface for incremental programs. It extends the normal Program API with methods for incrementally computing affected files and diagnostics. For details, see BuilderProgram and State.
| Interface | Factory Function | Use Case |
|---|---|---|
SemanticDiagnosticsBuilderProgram | createSemanticDiagnosticsBuilderProgram | Language service / watch mode diagnostics |
EmitAndSemanticDiagnosticsBuilderProgram | createEmitAndSemanticDiagnosticsBuilderProgram | Watch mode emit |
Sources: src/compiler/builder.ts7-10 src/compiler/builder.ts35 src/compiler/builder.ts78
BuilderState (in src/compiler/builderState.ts) is the internal data structure that tracks the state of every source file in the compilation. It stores:
fileInfos: A Map<Path, FileInfo> recording each file's version and computed signature. src/compiler/builderState.ts66referencedMap: Tracks which files are referenced by other files. src/compiler/builderState.ts72semanticDiagnosticsPerFile: Cached diagnostics per file to avoid recomputing them. src/compiler/builder.ts213File signature is typically the hash of a file's emitted .d.ts output. If a file's source changes but its public API does not, its signature stays the same, preventing unnecessary downstream re-checks. src/compiler/builder.ts172
Sources: src/compiler/builderState.ts62-98 src/compiler/builder.ts209-225
After a successful incremental build, the compiler serializes BuilderState into a .tsbuildinfo file. This JSON file acts as the persistent cache for the next invocation.
The path is computed by getTsBuildInfoEmitOutputFilePath. src/compiler/builder.ts55
The file includes:
program: Serialized file names, signatures, and diagnostics.version: The TypeScript version that wrote the file. src/compiler/watchPublic.ts119On the next run, readBuilderProgram attempts to restore the state. If the version mismatches, the cache is discarded. src/compiler/watchPublic.ts106-121
Build info serialization flow
Sources: src/compiler/watchPublic.ts106-121 src/compiler/builder.ts55
UpToDateStatusType is used by the solution builder to determine whether a project needs to be rebuilt. For details, see Up-To-Date Checking.
| Status | Meaning |
|---|---|
UpToDate | All outputs are newer than all inputs. |
UpToDateWithUpstreamTypes | Upstream sources changed, but their .d.ts did not; only touch timestamps. |
OutputMissing | One or more output files do not exist. |
OutOfDateWithSelf | An input source file is newer than the project's own outputs. |
OutOfDateWithUpstream | An upstream project's outputs are newer than this project's outputs. |
Sources: src/compiler/tsbuild.ts10-38 src/compiler/tsbuild.ts79-87
The solution builder (SolutionBuilder) is activated by tsc --build. It coordinates multi-project builds based on the references array in tsconfig.json. For details, see Project References.
The solution builder performs a topological sort of the project graph and builds projects in dependency order. It uses the UpToDateStatus to decide whether to invoke a full build, a "pseudo-build" (updating timestamps), or skip the project entirely.
System to Code Entity Mapping
Sources: src/compiler/tsbuild.ts41-55 src/compiler/tsbuildPublic.ts136-167 src/compiler/builder.ts209-225
The incremental builder integrates with watch mode via createWatchProgram. The WatchCompilerHost uses BuilderProgram to compute the minimal set of affected files after a change, rather than re-checking the whole project. src/compiler/watchPublic.ts160-173
In multi-project scenarios, createSolutionBuilderWithWatch watches all projects in the graph and triggers downstream builds when an upstream project emits new declaration files.
Sources: src/compiler/watch.ts193-213 src/compiler/watchPublic.ts160-173