typecheck and build tasks and more granular outputs for typecheck (#30549)
## Current Behavior
There is no dependency between the inferred `typecheck` and `build`
tasks. Depending on their run order, this can result in duplicated
processing (type-checking, `.d.ts` generation). Given there's no
explicit dependency, the order would be non-deterministic.
Additionally, when `outDir` is set in the tsconfig files, it's used
as-is in the currently inferred outputs for `typecheck`. This can result
in extra files being cached for the task.
## Expected Behavior
For optimum performance, the inferred `typecheck` task should depend on
the `build` task. The `typecheck` task's outputs should be more granular
so that only the relevant files (declaration files and declaration map
files if enabled) are cached.
### Explanation
Consider a typical setup with specific tsconfig file for files with
different concerns:
- tsconfig.lib.json: TS configuration for the library runtime files
- tsconfig.spec.json: TS configuration for the unit test files
- tsconfig.json: TS solution configuration, a solution file that
references the specific config files above
When running `tsc -b tsconfig.lib.json --verbose` (build), we can see
how the `tsconfig.lib.json` TS project is built:
```bash
Projects in this build:
* tsconfig.lib.json
Project 'tsconfig.lib.json' is out of date because output file 'dist/tsconfig.lib.tsbuildinfo' does not exist
Building project '<workspace root>/packages/pkg1/tsconfig.lib.json'...
```
After that, if we run `tsc -b tsconfig.json --emitDeclarationOnly
--verbose` (typecheck), we'll see how the `tsc` output for
`tsconfig.lib.json` is reused:
```bash
Projects in this build:
* tsconfig.lib.json
* tsconfig.spec.json
* tsconfig.json
Project 'tsconfig.lib.json' is up to date because newest input 'src/lib/file.ts' is older than output 'dist/tsconfig.lib.tsbuildinfo'
Project 'tsconfig.spec.json' is out of date because output file 'out-tsc/jest/tsconfig.spec.tsbuildinfo' does not exist
Building project '<workspace root>/packages/pkg1/tsconfig.spec.json'...
```
The relevant bit above is `Project 'tsconfig.lib.json' is up to date
because newest input 'src/lib/file.ts' is older than output
'dist/tsconfig.lib.tsbuildinfo'`. Because the initial `build` task
already typechecks and produces `.d.ts` files for the
`tsconfig.lib.json`, when the `typecheck` task runs, `tsc` identifies
that the outputs for that config files were already produced and can be
reused.
If we were to run the tasks in the inverse order, the results would be
different:
```bash
> npx tsc -b tsconfig.json --emitDeclarationOnly --verbose
Projects in this build:
* tsconfig.lib.json
* tsconfig.spec.json
* tsconfig.json
Project 'tsconfig.lib.json' is out of date because output file 'dist/tsconfig.lib.tsbuildinfo' does not exist
Building project '<workspace root>/packages/pkg1/tsconfig.lib.json'...
Project 'tsconfig.spec.json' is out of date because output file 'out-tsc/jest/tsconfig.spec.tsbuildinfo' does not exist
Building project '<workspace root>/packages/pkg1/tsconfig.spec.json'...
> npx tsc -b tsconfig.lib.json --verbose
Projects in this build:
* tsconfig.lib.json
Project 'tsconfig.lib.json' is out of date because buildinfo file 'dist/tsconfig.lib.tsbuildinfo' indicates there is change in compilerOptions
Building project '<workspace root>/packages/pkg1/tsconfig.lib.json'...
```
Note how when the `build` task is run, `tsc` identifies that there was a
change in `compilerOptions` (`--emitDeclarationOnly`) and it requires
building the project. This is because the `typecheck` task only
generates declaration files and the `build` task must also emit the
transpiled `.js` files.
### Benchmark
Running those two different flows in a simple (non-Nx) project with a TS
configuration structure like the one mentioned above and with 5000 TS
files split in half for runtime and test files yields the following:
```bash
hyperfine -r 5 -p "rm -rf dist out-tsc" \
-n "build => typecheck" "npx tsc -b tsconfig.lib.json && npx tsc -b --emitDeclarationOnly" \
-n "typecheck => build" "npx tsc -b tsconfig.json --emitDeclarationOnly && npx tsc -b tsconfig.lib.json"
Benchmark 1: build => typecheck
Time (mean ± σ): 6.832 s ± 0.094 s [User: 11.361 s, System: 1.060 s]
Range (min … max): 6.734 s … 6.985 s 5 runs
Benchmark 2: typecheck => build
Time (mean ± σ): 8.789 s ± 0.015 s [User: 14.817 s, System: 1.267 s]
Range (min … max): 8.771 s … 8.812 s 5 runs
Summary
build => typecheck ran
1.29 ± 0.02 times faster than typecheck => build
```
## Related Issue(s)
Fixes #
fix(js): infer dependency between
typecheck and build tasks and more granular outputs for typecheck (#30549)
fix(js): infer dependency between
typecheck and build tasks and more granular outputs for typecheck (#30549)
cleanup(react-native): use native fetch for isPackagerRunning check and remove
node-fetch dependency (#29568)
Smart Monorepos · Fast CI
Build system, optimized for monorepos, with AI-powered architectural awareness and advanced CI capabilities.
Create a new Nx workspace with
npx create-nx-workspace
...or run
npx nx init
to add Nx to your existing workspace to get faster task scheduling, caching and more. More in the docs.
Learn about CI with Nx Cloud
Nx Cloud connects directly to your existing CI setup, helping you scale your monorepos on CI by leveraging remote caching, task distribution across multiple machines, automated e2e test splitting and automated task flakiness detection
Connect your existing Nx workspace with
npx nx connect
Learn more in the Nx CI docs »
Useful links
Want to help?
If you want to file a bug or submit a PR, read up on our guidelines for contributing and watch this video that will help you get started.

Core Team
| Victor Savkin | Jason Jean | Benjamin Cabanes | Jack Hsu |
|---|---|---|---|
| vsavkin | FrozenPandaz | bcabanes | jaysoo |
| James Henry | Jon Cammisuli | Isaac Mann | Juri Strumpflohner |
|---|---|---|---|
| JamesHenry | cammisuli | isaacplmann | juristr |
| Philip Fulcher | Caleb Ukle | Katerina Skroumpelou | Colum Ferry |
|---|---|---|---|
| philipjfulcher | barbados-clemens | mandarini | Coly010 |
| Emily Xiong | Miroslav Jonaš | Leosvel Pérez Espinosa | Zachary DeRose |
|---|---|---|---|
| xiongemi | meeroslav | leosvelperez | ZackDeRose |
| Craigory Coppola | Chau Tran | Nicholas Cunningham | Max Kless |
|---|---|---|---|
| AgentEnder | nartc | ndcunningham | MaxKless |
Description
Languages
TypeScript
95%
Rust
2.9%
JavaScript
1.3%
Kotlin
0.3%
MDX
0.3%
Other
0.1%