web-infra-dev / web-infra-dev/rslint

[Bug]: Type-aware rules are silently ignored if tsconfig.json was not found for that TypeScript file

Open
#1,225 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.