Introduction
The tsc --build (or tsc -b) command is purpose-built for multi-project TypeScript setups. Unlike plain tsc, it understands project references, builds dependencies before dependents, and uses .tsbuildinfo files for incremental compilation. It is the correct way to compile TypeScript monorepos.
Key Concepts
- tsc --build (-b): A compilation mode that respects project references and builds in dependency order.
- .tsbuildinfo: A file storing incremental compilation state, allowing the compiler to skip unchanged files.
- Incremental Compilation: Only recompiling files that changed since the last build.
Real World Context
In a monorepo with 50 packages, running tsc on each package individually is slow and error-prone (wrong order, stale declarations). tsc --build handles the dependency graph automatically and only recompiles what changed.
Deep Dive
Basic Usage
bash# Build the current project and all its references tsc --build # Build a specific project tsc --build apps/api/tsconfig.json # Watch mode — rebuild on changes across all projects tsc --build --watch # Clean all build outputs tsc --build --clean # Force rebuild (ignore .tsbuildinfo) tsc --build --force
How Incremental Works
When composite: true or incremental: true is set, TypeScript writes a .tsbuildinfo file after compilation:
json{ "compilerOptions": { "composite": true, "incremental": true, "tsBuildInfoFile": "./dist/.tsbuildinfo" } }
On subsequent builds, TypeScript reads this file and skips files whose content hash has not changed. This can reduce build times by 80-90% for large projects.
Build Order
Given references:
shared → database → api
shared → ui → web
tsc --build compiles in topological order: shared first (no dependencies), then database and ui (depend on shared), then api and web (depend on database/ui respectively).
Verbose Output
bashtsc --build --verbose # Output: # Project 'libs/shared' is up to date # Building project 'apps/api'... # Project 'apps/web' is up to date
Common Pitfalls
- Using plain tsc in a monorepo — Plain
tscdoes not understand references. It compiles a single project and may use stale.d.tsfiles from dependencies. - Stale .tsbuildinfo files — If you manually move or delete files, the
.tsbuildinfocache may be stale. Usetsc --build --forceto do a clean rebuild.
Best Practices
- Always use tsc --build for monorepos — It is the only mode that correctly handles project references.
- Add .tsbuildinfo to .gitignore — These files are machine-specific build caches and should not be committed.
Summary
tsc --buildcompiles projects in dependency order using project references..tsbuildinfofiles enable incremental compilation, skipping unchanged files.- Use
--watchfor development and--cleanto remove outputs. - Always use
tsc --buildinstead of plaintscin multi-project setups.
Code Examples
# Common tsc --build commands
# Build all projects from root
tsc --build
# Build with verbose output to see what's happening
tsc --build --verbose
# Watch mode — recompile on any file change
tsc --build --watch
# Clean all outputs (.js, .d.ts, .tsbuildinfo)
tsc --build --clean
# Force full rebuild, ignoring cached .tsbuildinfo
tsc --build --force
# Build a specific project and its dependencies
tsc --build apps/api/tsconfig.json