-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(typecheck): improve error message when tsc outputs help text #9214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sheremet-va
merged 20 commits into
vitest-dev:main
from
Ujjwaljain16:fix/typecheck-tsconfig-missing-error
Dec 23, 2025
Merged
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
c6f2eab
fix(typecheck): improve error message when tsc outputs help text
Ujjwaljain16 5ce857b
test(typecheck): add unit tests for help text detection
Ujjwaljain16 441a6e9
Merge branch 'main' into fix/typecheck-tsconfig-missing-error
Ujjwaljain16 f8f1165
Merge branch 'main' into fix/typecheck-tsconfig-missing-error
Ujjwaljain16 26f4b71
fix(typecheck): fix Windows CI failure for non-existing typechecker c…
Ujjwaljain16 ecc15fd
fix(typecheck): move winTimeout declaration before use to fix linting…
Ujjwaljain16 0691f0d
test(typecheck): replace mocked tests with integration test
Ujjwaljain16 46bf95c
fix(typecheck): improve error message when tsconfig is missing\n\nDet…
Ujjwaljain16 a2d9ba2
Merge branch 'main' into fix/typecheck-tsconfig-missing-error
Ujjwaljain16 07b408c
style: fix linting errors
Ujjwaljain16 609930f
fix: use proper typecheck test file pattern
Ujjwaljain16 cc0a388
Merge branch 'fix/typecheck-tsconfig-missing-error' of https://github…
Ujjwaljain16 f09c5d6
fix: use test-d.ts pattern to trigger typecheck execution
Ujjwaljain16 c12e7f4
chore: remove debug log and document test approach
Ujjwaljain16 dfe2b54
fix lint
Ujjwaljain16 130d597
refactor(test): use createFile utility and static imports per review …
Ujjwaljain16 3468560
Merge branch 'main' into fix/typecheck-tsconfig-missing-error
Ujjwaljain16 7874e85
Merge branch 'main' into fix/typecheck-tsconfig-missing-error
Ujjwaljain16 a0e8efb
refactor: remove console.error and redundant mkdirSync per review
Ujjwaljain16 d5ec671
refactor: remove console.error and redundant mkdirSync per review
Ujjwaljain16 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| import type { TestProject } from '../../../packages/vitest/src/node/project' | ||
| import { describe, expect, it } from 'vitest' | ||
| import { Typechecker } from '../../../packages/vitest/src/typecheck/typechecker' | ||
|
|
||
| describe('Typechecker', () => { | ||
| it('detects tsc help text and throws clear error', async () => { | ||
| // Create a minimal mock project | ||
| const mockProject = { | ||
| config: { | ||
| root: '/fake/root', | ||
| typecheck: { | ||
| tsconfig: 'custom-tsconfig.json', | ||
| }, | ||
| }, | ||
| } as unknown as TestProject | ||
|
|
||
| const typechecker = new Typechecker(mockProject) | ||
| typechecker.setFiles([]) | ||
|
|
||
| // Simulate tsc outputting help text (what happens when tsconfig is missing) | ||
| const tscHelpOutput = `tsc: The TypeScript Compiler - Version 5.9.3 | ||
|
|
||
| COMMON COMMANDS | ||
|
|
||
| tsc | ||
| Compiles the current project (tsconfig.json in the working directory.) | ||
|
|
||
| tsc app.ts util.ts | ||
| Ignoring tsconfig.json, compiles the specified files with default compiler options.` | ||
|
|
||
| // The prepareResults method should detect help text and throw a clear error | ||
| await expect( | ||
| // @ts-expect-error - accessing protected method for testing | ||
| typechecker.prepareResults(tscHelpOutput), | ||
| ).rejects.toThrow('TypeScript compiler returned help text instead of type checking results') | ||
|
|
||
| try { | ||
| // @ts-expect-error - accessing protected method for testing | ||
| await typechecker.prepareResults(tscHelpOutput) | ||
| } | ||
| catch (error: any) { | ||
| // Verify error message contains helpful information | ||
| expect(error.message).toContain('This usually means the tsconfig file was not found') | ||
| expect(error.message).toContain('custom-tsconfig.json') | ||
| expect(error.message).toContain('Possible solutions:') | ||
| } | ||
| }) | ||
|
|
||
| it('detects help text with "COMMON COMMANDS" marker', async () => { | ||
| const mockProject = { | ||
| config: { | ||
| root: '/fake/root', | ||
| typecheck: {}, | ||
| }, | ||
| } as unknown as TestProject | ||
|
|
||
| const typechecker = new Typechecker(mockProject) | ||
| typechecker.setFiles([]) | ||
|
|
||
| // Help text might only contain COMMON COMMANDS without version | ||
| const tscHelpOutput = `COMMON COMMANDS | ||
|
|
||
| tsc | ||
| Compiles the current project (tsconfig.json in the working directory.)` | ||
|
|
||
| await expect( | ||
| // @ts-expect-error - accessing protected method for testing | ||
| typechecker.prepareResults(tscHelpOutput), | ||
| ).rejects.toThrow('TypeScript compiler returned help text') | ||
| }) | ||
|
|
||
| it('does not throw error for normal tsc output', async () => { | ||
| const mockProject = { | ||
| config: { | ||
| root: '/fake/root', | ||
| typecheck: {}, | ||
| }, | ||
| } as unknown as TestProject | ||
|
|
||
| const typechecker = new Typechecker(mockProject) | ||
| typechecker.setFiles([]) | ||
|
|
||
| // Normal tsc error output (not help text) | ||
| const normalTscOutput = `test.ts(5,10): error TS2322: Type 'string' is not assignable to type 'number'.` | ||
|
|
||
| // Should not throw for normal tsc errors | ||
| // Note: This will process the output normally | ||
| const result = await | ||
| // @ts-expect-error - accessing protected method for testing | ||
| typechecker.prepareResults(normalTscOutput) | ||
|
|
||
| expect(result).toBeDefined() | ||
| expect(result.files).toBeDefined() | ||
| }) | ||
| }) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test doesn't actually test the functionality, it mocks everything. Please, add a test following the policy from AGENTS.md:
vitest/AGENTS.md
Line 41 in 60642b3
Create a fixture or use
runInlineTeststo run tests.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The “help text” scenario cannot be integration-tested because
tscalwayssearches parent directories for tsconfig.json files. Even with runInlineTests,
tsc still inherits a real working directory and climbs to the Vitest monorepo
root, where tsconfig files exist.
Because of this, tsc will never emit its help text in CI or in Vitest’s test
environment, and automated tests cannot reliably trigger this condition.
@sheremet-va
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you just generate an invalid tsconfig file then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sheremet-va Thank you for the suggestion! I attempted the invalid tsconfig approach but ran into a technical constraint I'd like your input on.
Problem: tsc Help Text Trigger Conditions
After testing, I found that
tsconly outputs help text under these conditions:tsctsc --unknownFlag--helpHowever, Vitest's typechecker always invokes tsc with valid arguments:
Invalid
tsconfig.jsonAttemptsrunInlineTestsConfigtscOutput'tsconfig.json': '{ invalid }'tscruns'tsconfig.json': '{}'error TS18003: No inputs were foundcompilerOptions'tsconfig.json': '{"files":[]}'error TS18003: No inputs were foundRoot Cause
When
tscis invoked with-p <file>and the config file is structurally valid JSON (even if semantically incorrect), it enters normal compiler mode. In this mode,tscemits specific diagnostic errors and never falls back to printing help text.Help text is only produced when
tscitself is invoked with invalid or missing CLI arguments, which does not occur in Vitest’s invocation path.Current Solution: Test Executable Stub
I implemented a temporary executable that outputs tsc help text:
Is there a specific tsconfig.json structure or tsc invocation pattern I'm missing that would trigger help text output when called with -p ?
Alternatively, is the test executable approach acceptable for this edge case, or would you prefer:
A different testing strategy you have in mind
Modifying how Vitest invokes tsc for this specific test scenario