Skip to content

fix(bundling): skip unnecessary type-check in TS Solution Setup when skipTypeCheck is true#34493

Merged
jaysoo merged 2 commits intonrwl:masterfrom
wewelll:fix/js-noEmit-composite-tsbuildinfo
Feb 24, 2026
Merged

fix(bundling): skip unnecessary type-check in TS Solution Setup when skipTypeCheck is true#34493
jaysoo merged 2 commits intonrwl:masterfrom
wewelll:fix/js-noEmit-composite-tsbuildinfo

Conversation

@wewelll
Copy link
Contributor

@wewelll wewelll commented Feb 18, 2026

Current Behavior

In TS Solution Setup, the esbuild executor forces runTypeCheck even when skipTypeCheck: true and declaration: false, due to the || options.isTsSolutionSetup condition in esbuild.impl.ts (lines 139-140 and 195).

When declaration: false, this type check runs in noEmit mode with ignoreDiagnostics: true — making it completely pointless (no declarations emitted, no diagnostics reported). Its only observable effect is writing a poisoned 19-byte tsbuildinfo file that causes race conditions with tsc --build.

Expected Behavior

When skipTypeCheck: true and declaration: false, the esbuild executor should not run type checking at all. The isTsSolutionSetup override should only force type checking when declarations actually need to be generated.

Fix

Primary: Skip unnecessary type check (esbuild.impl.ts)

 // Non-watch mode (line 195) - if (!options.skipTypeCheck || options.isTsSolutionSetup) { + if (!options.skipTypeCheck || (options.isTsSolutionSetup && options.declaration)) { // Watch mode (lines 139-140) - options.isTsSolutionSetup + (options.isTsSolutionSetup && options.declaration)

Only force type checking in TS Solution Setup when declarations need to be generated. This eliminates the pointless type check entirely.

Defense-in-depth: Prevent tsbuildinfo in noEmit mode (run-type-check.ts)

- : { noEmit: true }; + : { noEmit: true, composite: false };

Setting composite: false alongside noEmit: true prevents TypeScript from writing tsbuildinfo files, protecting against this class of bug from any caller of runTypeCheck.

Why This is Safe

Scenario Before After
skipTypeCheck: false, declaration: false, isTsSolutionSetup: true Runs type check (noEmit) Still runs (!false || ... = true)
skipTypeCheck: false, declaration: true, isTsSolutionSetup: true Runs type check (emitDeclarationOnly) Still runs
skipTypeCheck: true, declaration: true, isTsSolutionSetup: true normalize.ts overrides skipTypeCheck to false; runs type check Still runs (same normalization)
skipTypeCheck: true, declaration: false, isTsSolutionSetup: true Runs pointless type check (noEmit + ignoreDiagnostics), writes poisoned tsbuildinfo Skipped entirely

The only behavior change is in the last row — the case where the type check was doing nothing useful but causing harm.

Related Issue(s)

Fixes #34492

@wewelll wewelll requested a review from a team as a code owner February 18, 2026 09:37
@wewelll wewelll requested a review from leosvelperez February 18, 2026 09:37
@netlify
Copy link

netlify bot commented Feb 18, 2026

Deploy Preview for nx-docs canceled.

Name Link
🔨 Latest commit 0714e5c
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/69958876ae28ec0008535e2e
@netlify
Copy link

netlify bot commented Feb 18, 2026

Deploy Preview for nx-dev canceled.

Name Link
🔨 Latest commit 5c079b0
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/699cceb8724fb30008086c10
…kipTypeCheck is true In TS Solution Setup, the esbuild executor forces runTypeCheck even when skipTypeCheck: true and declaration: false. This runs a type check in noEmit mode that suppresses all diagnostics (via ignoreDiagnostics: true), making it completely pointless -- except for its harmful side effect of writing a poisoned 19-byte tsbuildinfo file that causes race conditions with tsc --build. Primary fix (esbuild.impl.ts): Only force type-check in TS Solution Setup when declarations actually need to be generated (isTsSolutionSetup && declaration). When skipTypeCheck is true and declaration is false, the type check is skipped entirely. Defense-in-depth (run-type-check.ts): Also set composite: false in the noEmit code path to prevent tsbuildinfo writes from any caller, since composite: true + noEmit: true still triggers TypeScript to write a minimal tsbuildinfo file.
@wewelll wewelll force-pushed the fix/js-noEmit-composite-tsbuildinfo branch from 0714e5c to 505473e Compare February 18, 2026 10:07
@wewelll wewelll changed the title fix(js): set composite to false when running type-check in noEmit mode fix(esbuild): skip unnecessary type-check in TS Solution Setup when skipTypeCheck is true Feb 18, 2026
@jaysoo jaysoo changed the title fix(esbuild): skip unnecessary type-check in TS Solution Setup when skipTypeCheck is true fix(bundling): skip unnecessary type-check in TS Solution Setup when skipTypeCheck is true Feb 23, 2026
@nx-cloud
Copy link
Contributor

nx-cloud bot commented Feb 23, 2026

View your CI Pipeline Execution ↗ for commit 5c079b0

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 56m 47s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 3m 19s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 8s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-23 23:25:01 UTC

Copy link
Contributor

@nx-cloud nx-cloud bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud is proposing a fix for your failed CI:

Our changes apply Prettier formatting to the conditional statement in esbuild.impl.ts that was modified in the previous commit. The long conditional checking skipTypeCheck and isTsSolutionSetup has been reformatted to span multiple lines, ensuring compliance with the project's code style standards and fixing the format:check failure.

Tip

We verified this fix by re-running nx-cloud record -- nx format:check.

Suggested Fix changes
diff --git a/packages/esbuild/src/executors/esbuild/esbuild.impl.ts b/packages/esbuild/src/executors/esbuild/esbuild.impl.ts index dd47fba365..f92c181e70 100644 --- a/packages/esbuild/src/executors/esbuild/esbuild.impl.ts +++ b/packages/esbuild/src/executors/esbuild/esbuild.impl.ts @@ -192,7 +192,10 @@ export async function* esbuildExecutor( ); } else { // Run type-checks first and bail if they don't pass. - if (!options.skipTypeCheck || (options.isTsSolutionSetup && options.declaration)) { + if ( + !options.skipTypeCheck || + (options.isTsSolutionSetup && options.declaration) + ) { const { errors } = await runTypeCheck(options, context); if (errors.length > 0) { yield { success: false }; 

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.

Because this branch comes from a fork, it is not possible for us to apply fixes directly, but you can apply the changes locally using the available options below.

Apply changes locally with:

npx nx-cloud apply-locally U7b9-UZbX 

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

@jaysoo jaysoo merged commit bdeeb03 into nrwl:master Feb 24, 2026
16 of 17 checks passed
FrozenPandaz pushed a commit that referenced this pull request Feb 26, 2026
…skipTypeCheck is true (#34493) ## Current Behavior In TS Solution Setup, the esbuild executor forces `runTypeCheck` even when `skipTypeCheck: true` and `declaration: false`, due to the `|| options.isTsSolutionSetup` condition in `esbuild.impl.ts` (lines 139-140 and 195). When `declaration: false`, this type check runs in `noEmit` mode with `ignoreDiagnostics: true` — making it **completely pointless** (no declarations emitted, no diagnostics reported). Its only observable effect is writing a poisoned 19-byte tsbuildinfo file that causes race conditions with `tsc --build`. ## Expected Behavior When `skipTypeCheck: true` and `declaration: false`, the esbuild executor should not run type checking at all. The `isTsSolutionSetup` override should only force type checking when declarations actually need to be generated. ## Fix ### Primary: Skip unnecessary type check (`esbuild.impl.ts`) ```diff // Non-watch mode (line 195) - if (!options.skipTypeCheck || options.isTsSolutionSetup) { + if (!options.skipTypeCheck || (options.isTsSolutionSetup && options.declaration)) { // Watch mode (lines 139-140) - options.isTsSolutionSetup + (options.isTsSolutionSetup && options.declaration) ``` Only force type checking in TS Solution Setup when declarations need to be generated. This eliminates the pointless type check entirely. ### Defense-in-depth: Prevent tsbuildinfo in `noEmit` mode (`run-type-check.ts`) ```diff - : { noEmit: true }; + : { noEmit: true, composite: false }; ``` Setting `composite: false` alongside `noEmit: true` prevents TypeScript from writing tsbuildinfo files, protecting against this class of bug from any caller of `runTypeCheck`. ## Why This is Safe | Scenario | Before | After | |----------|--------|-------| | `skipTypeCheck: false`, `declaration: false`, `isTsSolutionSetup: true` | Runs type check (noEmit) | Still runs (`!false \|\| ...` = true) | | `skipTypeCheck: false`, `declaration: true`, `isTsSolutionSetup: true` | Runs type check (emitDeclarationOnly) | Still runs | | `skipTypeCheck: true`, `declaration: true`, `isTsSolutionSetup: true` | normalize.ts overrides skipTypeCheck to false; runs type check | Still runs (same normalization) | | **`skipTypeCheck: true`, `declaration: false`, `isTsSolutionSetup: true`** | **Runs pointless type check (noEmit + ignoreDiagnostics), writes poisoned tsbuildinfo** | **Skipped entirely** | The only behavior change is in the last row — the case where the type check was doing nothing useful but causing harm. ## Related Issue(s) Fixes #34492 --------- Co-authored-by: Jack Hsu <jack.hsu@gmail.com> (cherry picked from commit bdeeb03)
FrozenPandaz pushed a commit that referenced this pull request Feb 26, 2026
…skipTypeCheck is true (#34493) ## Current Behavior In TS Solution Setup, the esbuild executor forces `runTypeCheck` even when `skipTypeCheck: true` and `declaration: false`, due to the `|| options.isTsSolutionSetup` condition in `esbuild.impl.ts` (lines 139-140 and 195). When `declaration: false`, this type check runs in `noEmit` mode with `ignoreDiagnostics: true` — making it **completely pointless** (no declarations emitted, no diagnostics reported). Its only observable effect is writing a poisoned 19-byte tsbuildinfo file that causes race conditions with `tsc --build`. ## Expected Behavior When `skipTypeCheck: true` and `declaration: false`, the esbuild executor should not run type checking at all. The `isTsSolutionSetup` override should only force type checking when declarations actually need to be generated. ## Fix ### Primary: Skip unnecessary type check (`esbuild.impl.ts`) ```diff // Non-watch mode (line 195) - if (!options.skipTypeCheck || options.isTsSolutionSetup) { + if (!options.skipTypeCheck || (options.isTsSolutionSetup && options.declaration)) { // Watch mode (lines 139-140) - options.isTsSolutionSetup + (options.isTsSolutionSetup && options.declaration) ``` Only force type checking in TS Solution Setup when declarations need to be generated. This eliminates the pointless type check entirely. ### Defense-in-depth: Prevent tsbuildinfo in `noEmit` mode (`run-type-check.ts`) ```diff - : { noEmit: true }; + : { noEmit: true, composite: false }; ``` Setting `composite: false` alongside `noEmit: true` prevents TypeScript from writing tsbuildinfo files, protecting against this class of bug from any caller of `runTypeCheck`. ## Why This is Safe | Scenario | Before | After | |----------|--------|-------| | `skipTypeCheck: false`, `declaration: false`, `isTsSolutionSetup: true` | Runs type check (noEmit) | Still runs (`!false \|\| ...` = true) | | `skipTypeCheck: false`, `declaration: true`, `isTsSolutionSetup: true` | Runs type check (emitDeclarationOnly) | Still runs | | `skipTypeCheck: true`, `declaration: true`, `isTsSolutionSetup: true` | normalize.ts overrides skipTypeCheck to false; runs type check | Still runs (same normalization) | | **`skipTypeCheck: true`, `declaration: false`, `isTsSolutionSetup: true`** | **Runs pointless type check (noEmit + ignoreDiagnostics), writes poisoned tsbuildinfo** | **Skipped entirely** | The only behavior change is in the last row — the case where the type check was doing nothing useful but causing harm. ## Related Issue(s) Fixes #34492 --------- Co-authored-by: Jack Hsu <jack.hsu@gmail.com> (cherry picked from commit bdeeb03)
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

2 participants