Open-Source Wikis

/

TypeScript

/

Features

/

Project references

microsoft/TypeScript

Project references

The mechanism by which a TypeScript codebase splits into smaller, mutually-referencing compilations that can be built independently and consumed via their .d.ts outputs.

Where project references touch the codebase

Subsystem File Role
Config parsing src/compiler/commandLineParser.ts Parses references array, validates project paths
Solution builder src/compiler/tsbuildPublic.ts Topological build order, up-to-date checks, multi-project compile
Solution-builder types src/compiler/tsbuild.ts BuildOptions, UpToDateStatus
Program src/compiler/program.ts redirectedReference plumbing for cross-project type references
Builder src/compiler/builder.ts .tsbuildinfo shape with cross-project info

Concept

A tsconfig.json declares dependencies on other projects:

{
  "compilerOptions": {
    "composite": true,
    "outDir": "./out"
  },
  "references": [{ "path": "../shared" }, { "path": "../utils" }]
}

composite: true enables --declaration, --declarationMap, --incremental, and disallows --noEmit. References point at directories containing other tsconfig.jsons.

When tsc -b is run, the solution builder:

  1. Loads the root tsconfig.json and recursively follows references.
  2. Topologically sorts the resulting DAG.
  3. For each project in order, asks: is this project up-to-date? If not, build it.
  4. Writes .tsbuildinfo per project so subsequent runs can short-circuit.

When a downstream Program resolves a reference to an upstream project's source, it transparently uses the upstream's .d.ts outputs instead — sources cross project boundaries only at type-level.

Up-to-date checks

getUpToDateStatusOfProject reads a project's .tsbuildinfo and decides one of:

  • UpToDate — skip
  • OutOfDateWithSelf — own sources changed
  • OutOfDateWithUpstream — an upstream project rebuilt
  • OutOfDateBuildInfo.tsbuildinfo missing or unparseable
  • OutOfDateOptionsCompilerOptions changed since last build
  • UpstreamOutOfDate / UpstreamBlocked — an upstream project itself isn't ready

These statuses give clear diagnostic output (e.g., Project '/abs/foo/tsconfig.json' is out of date because output 'foo.js' is older than input 'foo.ts') so users can debug build invalidations.

Cross-project resolution

When a downstream file imports "../shared/Logger":

  • The resolver detects the import lands inside a referenced project.
  • It substitutes the resolved file with the upstream's emitted .d.ts (under that project's outDir or declarationDir).
  • The downstream program records a redirectedReference mapping so the checker can correlate symbols across the boundary.

This means upstream projects' implementation files are never loaded into a downstream's type system — only their declarations.

Watch mode for build

tsc -b --watch (and the editor case via tsserver with project references) keeps the solution builder alive, watches every project's files, and rebuilds in topological order whenever a relevant change comes in. Cascading invalidation respects the up-to-date status — a leaf project change doesn't force re-checking unrelated projects unless their inputs depend on the changed outputs.

Diagnostics specific to references

  • TS6377: Cannot write file because it would overwrite input file — when project A's outDir lands inside project B's source set.
  • TS6378: Project references may not form a circular graph — cycle detection.
  • TS6306: Referenced project '{0}' must have setting "composite": true. — composite is mandatory.
  • TS6310: Referenced project '{0}' may not disable emit.noEmit: true is incompatible with being depended upon.

Tests

tests/cases/projects/ contains many multi-project fixtures, often with explicit referencesFiles setups. The tsbuild runner exercises them and compares against baselines.

Entry points for modification

See systems/build-mode and systems/watch-and-builder for the underlying primitives, and features/declaration-emit for what crosses project boundaries.

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

Project references – TypeScript wiki | Factory