A working editor is not a clean build
Project references divide a TypeScript codebase into cooperating compiler projects. A shared domain package might be used by an API and an administrative application. The dependency is a build relationship as well as an import relationship. If a developer has old generated declarations on disk, an editor may look healthy while a clean CI worker cannot compile the same repository.
Keep three questions separate: can TypeScript understand an import, can the build produce every dependency, and can the runtime resolve the emitted package? Passing one does not automatically answer the others. This guide focuses on declaration production and dependency order rather than runtime input validation or application state modeling.
Setup: describe the actual dependency graph
Inventory each tsconfig, package entry point, source directory and output directory. Record which packages depend on which others. For referenced projects, review the composite and declaration requirements in the documentation for the pinned compiler version. Make sure generated outputs do not overlap source files or outputs owned by another project.
From a disposable clean checkout, install from the lockfile and run the documented project build command. TypeScript's build mode, invoked with tsc -b, discovers referenced projects and builds those requiring work in dependency order. Ordinary tsc invocation is not an automatic replacement for this orchestration. Use the locally installed compiler so an unrelated global installation cannot change the result.
Illustrative incident: only one workstation passes
An illustrative application imports an internal pricing package. A developer's tests pass because yesterday's declaration files remain present. CI starts clean and reports that an expected dependency output has not been built. Re-running the editor does not establish whether the package graph is correct. No customer engagement or performance improvement is claimed by this example.
Capture the compiler version, command, first failing diagnostic, referenced config paths and package output listing. Preserve the failing clean build before trying multiple fixes. An error later in the log may simply be a consequence of the first missing dependency.
Troubleshooting: identify the missing build edge
| Symptom | Inspect | Question to answer |
|---|---|---|
| Dependency declaration is absent | Reference list and build entry point | Was the dependency included in the graph? |
| Local output differs from CI | Ignored files and clean checkout result | Is a stale artifact hiding the defect? |
| Compiler succeeds, runtime import fails | Package exports and emitted paths | Does runtime resolution match the built package? |
| Editing one package changes another output | outDir and rootDir ownership | Are output directories overlapping? |
Do not fix a missing reference by copying declaration files manually into CI. That creates an artifact with unclear provenance. Similarly, suppressing the diagnostic may leave consumers compiling against an obsolete contract while the runtime uses different JavaScript.
Corrective action and artifact policy
Correct the reference graph and give every project a clear output boundary. Decide whether generated outputs are built in CI, published as versioned packages or deliberately checked in. Apply that policy consistently. Build-mode dry and verbose options can help review the intended work before changing the pipeline, but retain a real clean build as acceptance evidence.
Keep incremental metadata and build caches scoped to the appropriate inputs and toolchain. A cache is an optimization, not the source of truth. When diagnosing, reproduce once without restored outputs in a disposable workspace; do not delete a developer's uncommitted source or production application directory. If dependency cycles appear, review package responsibilities rather than forcing an arbitrary order that only happens to pass today.
Verification, SLO and SOP
Run the clean build, change a shared exported type, and confirm that consumers are rebuilt and checked. Then test the emitted package with the actual runtime or bundler used by the application. Include a negative fixture whose consumer violates the changed contract; a build that incorrectly passes it is not protecting the boundary.
An internal build-reliability SLO can measure reproducible successful builds for valid changes, with failures attributed to code, infrastructure or dependency availability. It is distinct from a customer-facing application SLA. The SOP should record the build entry point, compiler version source, artifact ownership and safe cache-bypass procedure. Avoid promising a build speed gain without measurements from representative changes.
See JavaScript and TypeScript development and DevOps automation for coordinated application and pipeline work.
Technical reference
TypeScript project references, reviewed 19 October 2026. Compiler behavior should be checked against the pinned project version.