-
Notifications
You must be signed in to change notification settings - Fork 156
Remove "include": ["src"] from tsconfig.json in vp create vite:library template #1308
Description
Description
Projects generated by vp create vite:library include a tsconfig.json like the following:
{
"compilerOptions": {
"target": "esnext",
"lib": ["es2023"],
"moduleDetection": "force",
"module": "nodenext",
"moduleResolution": "nodenext",
"resolveJsonModule": true,
"types": ["node"],
"strict": true,
"noUnusedLocals": true,
"declaration": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": ["src"]
}The key issue is that the include field is limited to the src directory only. This causes the following problems.
Problem 1: Cannot auto-import items from src directory files outside of src
Files outside of the src directory cannot auto-import functions and other items from the src directory. For example, files in the tests directory cannot auto-import functions defined in src.
Steps to reproduce:
git clone https://github.com/mizdra-sandbox/repro-vp-lib-tsconfig-is-missingcd repro-vp-lib-tsconfig-is-missingcode --profile-temp .(using VS Code)- Open
tests/index.test.ts - Place the cursor after
fnand trigger completion- Expected behavior:
fnshould be suggested - Actual behavior:
fnis not suggested
- Expected behavior:
tsserver treats files in the src directory as part of the tsconfig.json project, but treats files in the tests directory as part of an "Inferred Project". An Inferred Project is one that tsserver automatically assigns to files that have no corresponding tsconfig.json. Since tsserver cannot auto-import items between files belonging to different projects, files in tests cannot auto-import items from files in src.
Problem 2: Expected compiler options are not applied to files outside src
The tsconfig.json includes "noUnusedLocals": true. While the src directory is affected by this option, the tests directory, vite.config.ts, and similar files are not. As a result, unused local variables in those files are not reported as errors.
Steps to reproduce:
git clone https://github.com/mizdra-sandbox/repro-vp-lib-tsconfig-is-missingcd repro-vp-lib-tsconfig-is-missingcode --profile-temp .(using VS Code)- Open
tests/index.test.ts - Add code containing an unused local variable (e.g.
const unused = 1;) - Run
vp check$ vp check VITE+ - The Unified Toolchain for the Web pass: All 7 files are correctly formatted (158ms, 14 threads) error: Lint or type issues found × typescript(TS2304): Cannot find name 'fn'. ╭─[tests/index.test.ts:3:1] 2 │ const unused = 1; 3 │ fn(); · ── ╰──── Found 1 error and 0 warnings in 3 files (140ms, 14 threads)
- No
noUnusedLocalserror is reported forconst unused = 1; - Expected behavior: if
noUnusedLocalswere applied, an "unused variable" error forunusedshould be reported in addition to the "cannot find name" error forfn
- No
Users would reasonably expect the same compiler options applied to src to also apply to files in tests, vite.config.ts, and similar locations. This behavior is therefore likely to cause confusion.
Suggested solution
Remove the "include" field from tsconfig.json in projects generated by vp create vite:library. Omitting "include" is equivalent to specifying "include": ["**/*"], which causes all TypeScript files to be treated as part of the tsconfig.json project. This resolves both problems described above.
Alternative
None.
Additional context
About projects generated by vp create vite:application
The tsconfig.json in projects generated by vp create vite:application also contains "include": ["src"], so the same problems occur. The "include" field should be removed there as well to broaden the scope.
Compiler options used by Inferred Projects
Files in tests, vite.config.ts, and similar locations belong to an Inferred Project, so Inferred Project settings are applied to them. In tsserver, the options used are either the values sent by the editor via a setCompilerOptionsForInferredProjects request, or the default values defined in TypeScript's src/server/project.ts.
- https://github.com/microsoft/vscode/blob/8d415912364f9b29d76ae6bfc59234e59e03dbc7/extensions/typescript-language-features/src/typescriptServiceClient.ts#L622-L630, https://github.com/microsoft/vscode/blob/8d415912364f9b29d76ae6bfc59234e59e03dbc7/extensions/typescript-language-features/src/tsconfig.ts#L23
- (when tsserver version >= 5.4.0)
"module": "Preserve","moduleResolution": "Bundler","target": "ES2022","allowImportingTsExtensions": true, ... - (when tsserver version < 5.4.0)
"module": "ESNext","moduleResolution": "Bundler","target": "ES2022","allowImportingTsExtensions": true, ...
- (when tsserver version >= 5.4.0)
- https://github.com/microsoft/TypeScript/blob/7b8cb3bdf82f400642b73173f941335775d6f730/src/server/project.ts#L590-L594, https://github.com/microsoft/TypeScript/blob/7b8cb3bdf82f400642b73173f941335775d6f730/src/services/services.ts#L1384
"module": "ESNext","moduleResolution": "Bundler","target": "ESNext","allowImportingTsExtensions": false, ...
In oxlint, the values defined in the CreateInferredProjectProgram function are used.
- https://github.com/oxc-project/tsgolint/blob/757a9968aeb3ab543515738d1a26aa95176b84ee/internal/utils/create_program.go#L124-L139
"module": "ESNext","moduleResolution": "Bundler","target": "ES2022","allowImportingTsExtensions": true, ...
Side effects of broadening the scope of tsconfig.json
Broadening the scope of tsconfig.json has some side effects.
Side effect 1: "module": "nodenext" and "moduleResolution": "nodenext" are applied to files outside src
The compiler options intended for src will also be applied to files in other directories. Of particular note are "module": "nodenext" and "moduleResolution": "nodenext". It is worth considering whether applying these to the tests directory, config files (e.g. vite.config.ts), and a scripts directory (e.g. https://github.com/vitest-dev/vitest/tree/main/scripts) is acceptable.
In my view, applying these options to tests and config files should not be a problem. The src directory is built by vp pack and tests is run by vp test; both are backed by Vite, which supports building code that assumes "module": "nodenext" and "moduleResolution": "nodenext".
Applying these options to config files should also be fine. Config files are either executed via Node.js Type Stripping (e.g. prettier.config.ts) or bundled before execution (e.g. vite.config.ts), and both execution models support code that assumes these module settings. The same applies to a scripts directory.
Therefore, this side effect is not a significant concern.
Side effect 2: Per-directory compiler options become harder to configure
In some cases, users may want to apply different compiler options per directory. For example, they may want "allowImportingTsExtensions": true for src and tests, but not for scripts.
If that is needed, a "solution-style" tsconfig.json can be added later to achieve per-directory configuration.
- https://www.typescriptlang.org/docs/handbook/project-references.html#overall-structure
- https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files
// tsconfig.json
{
"files": [],
"references": [
{ "path": "./tsconfig.default.json" }, // For `src` and `tests` directories
{ "path": "./tsconfig.scripts.json" } // For `scripts` directory
]
}// tsconfig.default.json
{
"compilerOptions": {
"target": "esnext",
"lib": ["es2023"],
"moduleDetection": "force",
"module": "nodenext",
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true
// ...
}
}// tsconfig.scripts.json
{
"compilerOptions": {
"target": "esnext",
"lib": ["es2023"],
"moduleDetection": "force",
"module": "nodenext",
"moduleResolution": "nodenext"
// "allowImportingTsExtensions": true,
// ...
}
}Since a workaround exists, this side effect is not a significant concern.
Validations
- Read the Contributing Guidelines.
- Confirm this request is for Vite+ itself and not for Vite, Vitest, tsdown, Rolldown, or Oxc.
- Check that there isn't already an issue requesting the same feature.
Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackPriority
Start date
Target date
Effort