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:
{
"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
- Set up a project structure where
tsconfig.json contains references only:
tsconfig.json:
{
"files": [],
"references": [
{ "path": "./tsconfig.node.json" }
]
}
tsconfig.node.json:
{
"include": ["index.ts"]
}
- Create an
index.ts with a floating promise and a syntax error:
console.log("233");
async function getPromise() {}
getPromise(); // Floating promise
- Run
rslint with the following rslint.config.ts (configured with the root tsconfig.json):
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",
},
},
]);
- Run
rslint. It only reports the no-console error but silently skips the @typescript-eslint/no-floating-promises error on index.ts.
Details
In a typical TypeScript monorepo setup, the root
tsconfig.jsonis configured as a solution-style config containing onlyreferencespointing to package-specific config files (e.g.,tsconfig.node.json), with its ownfilesset to empty:{ "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, neitherrslintnor standard file-basedeslintconfigurations 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.jsonunder basic setups, their feedback mechanisms differ significantly:tsconfig, outputting 0 warnings or errors. Developers are left unaware that type checks are not being run on their files.Detailed Linter Behavior Comparison
index.tsis only in referencedtsconfig.node.json)project: ["./tsconfig.json"]index.ts. Reports 0 errors/warnings forno-floating-promises.project: ["./tsconfig.node.json"]index.tsusing the sub-project tsconfig.projectService: trueindex.ts. Reports 0 errors/warnings forno-floating-promises.project: ["./tsconfig.json"]The file was not found in any of the provided project(s): index.ts.project: ["./tsconfig.node.json"]index.tsusing the sub-project tsconfig.project: true(Auto-lookup)tsconfig.jsonand failing to locate the file in its scope.projectService: truetsconfig.jsonautomatically.--type-aware(*)(*)Oxlint Behavior: Search fortsconfig.jsonupwards, recursively tracereferences, and if still not matched (or missing completely), fall back toCreateInferredProjectProgram(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
tsconfigproject structure. Force user to modify the config file, or manually ignore that inallowDefaultProjectfield or global ignores.Reproduce link
https://github.com/swwind/rslint-reference-repro
Reproduce Steps
tsconfig.jsoncontains references only:tsconfig.json:{ "files": [], "references": [ { "path": "./tsconfig.node.json" } ] }tsconfig.node.json:{ "include": ["index.ts"] }index.tswith a floating promise and a syntax error:rslintwith the followingrslint.config.ts(configured with the roottsconfig.json):rslint. It only reports theno-consoleerror but silently skips the@typescript-eslint/no-floating-promiseserror onindex.ts.