ESLint 9.0: Mandatory parserOptions.project for TypeScript rules
0 reputation · 03 Jun 2022, 18:41 UTC
0 reputation · 03 Jun 2022, 18:41 UTC
Starting with ESLint 9.0, any rule that relies on TypeScript type information (e.g., @typescript-eslint/no-unused-vars) now throws a configuration error unless parserOptions.project points to a valid tsconfig.json. The change is documented in the 9.0 release notes and is intended to enforce consistent type-aware linting across a codebase.
For projects that mix JavaScript and TypeScript, this requirement forces every workspace to maintain a tsconfig.json, even if only a subset of files contains TypeScript. In many monorepos, some packages contain only JavaScript and have no tsconfig.json, yet the global ESLint configuration still references parserOptions.project for the entire workspace.
ESLint documentation does not currently provide guidance on how to handle linting of TypeScript files when a tsconfig.json is absent or when only a subset of files should be type‑checked. This leaves teams uncertain whether to create a minimal in‑memory configuration, to skip TypeScript rules, or to restructure the repository.
Unresolved questions:
tsconfig.json when parserOptions.project is omitted for TypeScript rules?tsconfig.json?34775 reputation · 03 Jun 2022, 20:48 UTC
The requirement for parserOptions.project is not imposed by ESLint 9.0 itself, but by @typescript-eslint when type-aware rules are enabled. These rules (like @typescript-eslint/no-unused-vars with type checking) require a TypeScript program to function, which cannot be initialized without a valid tsconfig.json.
In mixed-language monorepos, the error occurs because a global configuration attempts to apply type-aware rules to JavaScript files that lack a TypeScript configuration. To resolve this, you must decouple your general linting from type-aware analysis.
Using ESLint's flat config (eslint.config.js), you should define multiple configuration objects. This allows you to apply type-aware rules only to files that have a project structure supporting them.
**/*.ts and **/*.tsx files. This is where you define parserOptions.project.project: true: Instead of hardcoding paths, setting project: true allows the parser to automatically find the nearest tsconfig.json for each file, which significantly reduces maintenance.import js from "@eslint/js";
import tsPlugin from "@typescript-eslint/eslint-plugin";
export default [\n // 1. Global settings for all files (No type-aware)
{
files: ["**/*.js", "**/*.jsx"],\n extends: [js.configs.recommended],
rules: {
"no-console": "warn"
}
},
n
// 2. Type-aware settings for TypeScript only
{
files: ["**/*.ts", "**/*.tsx"],
plugins: {
"@typescript-eslint": tsPlugin
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: true, // Auto-discovers tsconfig.json
},
rules: {
...tsPlugin.configs.recommendedTypeChecked.rules,
"@typescript-eslint/no-unused-vars": "error"
}
}
];
If a package contains TypeScript files but lacks a tsconfig.json, you have two viable paths:
tsconfig.json to the directory with just {"compilerOptions": {"include": ["*"]}}. This satisfies the parser without requiring complex build logic.parserOptions.project.Assumption: You are using the ESLint 9+ flat config format and @typescript-eslint version 7 or 8.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.