tsc runs through several distinct stages: parsing source into an abstract syntax tree, binding to build a symbol table, type-checking the AST against that table, and finally emitting plain JavaScript with all type syntax completely erased. These stages are genuinely separable — type-checking and emitting are different passes, which is why tsc can be configured to still emit JavaScript even when type errors are present. Project references let a large codebase be split into multiple tsconfig.json projects, each independently and incrementally compiled, which meaningfully speeds up builds in a monorepo.
Type errors don't necessarily stop JavaScript output
By default, tsc still emits JavaScript even when type errors exist — checking and emitting are separate passes. noEmitOnError changes this, refusing to emit any output at all if type-checking failed.
{
"compilerOptions": {
"noEmitOnError": true // refuse to emit .js files if there are type errors
}
}Incremental compilation
incremental caches information about the previous compilation in a .tsbuildinfo file, so a subsequent build only re-checks what actually changed — a meaningful speedup on large codebases, especially combined with --watch mode during development.
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo"
}
}Project references for large codebases
Splitting a large monorepo into multiple smaller projects, each with its own tsconfig.json and a references array pointing at its dependencies, lets tsc rebuild only the projects that actually changed rather than the entire codebase every time — a significant win for build time as a repository grows.
{
"compilerOptions": { "composite": true },
"references": [
{ "path": "../shared-utils" }
]
}2026 brought this whole pipeline its most significant change ever: TypeScript 7.0, which ports the entire compiler and language service to Go, went to Release Candidate in June 2026 and reached a full release on August 3, 2026. Microsoft reports typical speedups of roughly 8–12x on full builds — VS Code's own build time dropped from 125.7s to 10.6s in their benchmarks. The Go port was methodically translated from the existing TypeScript codebase rather than rewritten from scratch, with the stated goal of structurally identical checking behavior to TypeScript 6.0; the project tracks the handful of known, intentional behavioral differences in its own CHANGES.md rather than claiming zero differences at all.