web-infra-dev / web-infra-dev/rslint
[Bug]: Type-aware rules are silently ignored if tsconfig.json was not found for that TypeScript file
- Dominant language
- Go
- Stars
- 459
- Forks
- 33
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 376
Description
### Details
In a typical TypeScript monorepo setup, the root `tsconfig.json` is configured as a solution-style config containing only `references` pointing to package-specific config files (e.g., `tsconfig.node.json`), with its own `files` set to empty:
```json
{
"files": [],
"references": [
{ "path": "./tsconfig.node.json" }
]
}
```
When running linter checks from the workspace root, type-aware rules (like `@typescript-eslint/no-floating-promises`) require compiler program resolution. However, neither `rslint` nor standard file-based `eslint` configurations follow root project references by default.
#### The Problem: Silent Failure in rslint
While both linters fail to match the source file against the root `tsconfig.json` under basic setups, their feedback mechanisms differ significantly:
* **rslint fails silently**: It silently skips type-aware rules for files not matched in the `tsconfig`, outputting 0 warnings or errors. Developers are left unaware that type checks are not being run on their files.
* **ESLint reports explicit errors**: Depending on the configuration, ESLint will loudly report parsing errors or require explicit configuration, ensuring configuration issues do not go unnoticed.
#### Detailed Linter Behavior Comparison
| Linter | Configuration Scenario | Behavior (When target file `index.ts` is only in referenced `tsconfig.node.json`) |
| --- | --- | --- |
| **rslint** | `project: ["./tsconfig.json"]` | **Silently ignores** type-aware rules for `index.ts`. Reports 0 errors/warnings for `no-floating-promises`. |
| **rslint** | `project: ["./tsconfig.node.json"]` | **Succeeds** in linting: correctly matches `index.ts` using the sub-project tsconfig. |
| **rslint** | `projectService: true` | **Silently ignores** type-aware rules for `index.ts`. Reports 0 errors/warnings for `no-floating-promises`. |
| **ESLint** | `project: ["./tsconfig.json"]` | **Fails loudly** with parser error: `The file was not found in any of the provided project(s): index.ts`. |
| **ESLint** | `project: ["./tsconfig.node.json"]` | **Succeeds** in linting: correctly matches `index.ts` using the sub-project tsconfig. |
| **ESLint** | `project: true` (Auto-lookup) | **Fails loudly** after discovering the root `tsconfig.json` and failing to locate the file in its scope. |
| **ESLint** | `projectService: true` | **Succeeds** in linting: **it follows references and finds the correct `tsconfig.json` automatically.** |
| **oxlint** | `--type-aware` | **Succeeds gracefully** `(*)` |
`(*)` **Oxlint Behavior**: Search for `tsconfig.json` upwards, recursively trace `references`, and if still not matched (or missing completely), fall back to `CreateInferredProjectProgram` (an in-memory compilation program with ES2022, StrictNullChecks, etc.).
#### Proposed Solutions for rslint
**Warn/Fail**: If a tsconfig.json is not found for a TypeScript file, log a warning/error indicating that type-aware lint rules were skipped for the file because it isn't part of the target `tsconfig` project structure. Force user to modify the config file, or manually ignore that in `allowDefaultProject` field or global ignores.
### Reproduce link
https://github.com/swwind/rslint-reference-repro
### Reproduce Steps
1. Set up a project structure where `tsconfig.json` contains references only:
`tsconfig.json`:
```json
{
"files": [],
"references": [
{ "path": "./tsconfig.node.json" }
]
}
```
`tsconfig.node.json`:
```json
{
"include": ["index.ts"]
}
```
2. Create an `index.ts` with a floating promise and a syntax error:
```typescript
console.log("233");
async function getPromise() {}
getPromise(); // Floating promise
```
3. Run `rslint` with the following `rslint.config.ts` (configured with the root `tsconfig.json`):
```typescript
import { defineConfig } from "@rslint/core";
export default defineConfig([
{
files: ["**/*.ts"],
plugins: ["@typescript-eslint"],
languageOptions: {
parserOptions: { project: ["./tsconfig.json"] },
},
rules: {
"no-console": "error",
"@typescript-eslint/no-floating-promises": "error",
},
},
]);
```
4. Run `rslint`. It only reports the `no-console` error but silently skips the `@typescript-eslint/no-floating-promises` error on `index.ts`.
Contributor guide
Research direction
Start by running the linked reproduction with rslint.config.ts, the root tsconfig.json, tsconfig.node.json, and index.ts, then inspect how parserOptions project and projectService handle unmatched TypeScript files. Done means rslint no longer silently skips type-aware rules when no matching tsconfig project is found, but instead reports the configuration problem.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- eslint, typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100