This error occurs when you're using type-aware ESLint rules from @typescript-eslint but haven't configured the parser to provide type information. The fix involves configuring parserOptions with either projectService or project in your ESLint configuration file.
The "Type information for @typescript-eslint rule unavailable" error appears when you're using ESLint rules that require TypeScript's type checker (like @typescript-eslint/await-thenable, @typescript-eslint/no-floating-promises, or @typescript-eslint/strict-boolean-expressions), but your ESLint configuration hasn't been set up to provide parser services with type information. These type-aware rules need access to TypeScript's type system to analyze your code properly. Unlike syntax-based rules that only look at the code structure, type-aware rules need to understand what types your variables have, what functions return, and other semantic information that requires TypeScript compilation. The @typescript-eslint/parser needs to be configured with either parserOptions.projectService (recommended as of v8) or parserOptions.project to enable this functionality. Without this configuration, the parser cannot generate the type information that these advanced rules require.
The modern and recommended approach is to use projectService in your ESLint config. This is simpler and faster than the legacy project option:
// .eslintrc.js or .eslintrc.cjs
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
projectService: true,
tsconfigRootDir: __dirname,
},
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
};Or for ESM-based flat config (eslint.config.js):
// eslint.config.js
import tseslint from '@typescript-eslint/eslint-plugin';
import parser from '@typescript-eslint/parser';
export default [
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser,
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: tseslint.configs['recommended-type-checked'].rules,
},
];With projectService: true, the parser automatically finds the nearest tsconfig.json for each file.
If you need explicit control over which tsconfig files to use, configure the project option:
// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},
plugins: ['@typescript-eslint'],
extends: [
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
};For monorepos with multiple tsconfig files:
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: [
'./tsconfig.json',
'./packages/*/tsconfig.json',
'./apps/*/tsconfig.json',
],
tsconfigRootDir: __dirname,
},
};Important: Using project has a performance cost since it requires TypeScript to build type information for your entire project before ESLint can run.
Files must be included in your TypeScript project for type information to be available:
{
"compilerOptions": {
"strict": true,
// ... other options
},
"include": [
"src/**/*",
"tests/**/*",
"*.config.ts"
],
"exclude": [
"node_modules",
"dist",
"build"
]
}If you're linting config files (like .eslintrc.ts, vite.config.ts), make sure they're in the include array.
For files that shouldn't be type-checked but need to be linted, you can create a separate tsconfig.eslint.json:
{
"extends": "./tsconfig.json",
"include": [
"src/**/*",
"tests/**/*",
"*.config.ts",
".eslintrc.ts"
]
}Then reference it in your ESLint config:
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
}Ensure you have the necessary TypeScript ESLint packages installed:
# Install @typescript-eslint packages
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
# Or with yarn
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
# Or with pnpm
pnpm add -D @typescript-eslint/parser @typescript-eslint/eslint-pluginFor the latest features like projectService, ensure you're using version 8.0.0 or higher:
npm install --save-dev @typescript-eslint/parser@latest @typescript-eslint/eslint-plugin@latestVerify installation:
npm list @typescript-eslint/parser @typescript-eslint/eslint-pluginIf some files don't need type checking or cause issues, you can disable type-aware rules for them:
// .eslintrc.js
module.exports = {
// ... main config with projectService
overrides: [
{
// Disable type-aware linting for JavaScript files
files: ['*.js'],
extends: ['plugin:@typescript-eslint/disable-type-checked'],
},
{
// Disable for config files not in tsconfig
files: ['.*.js', '*.config.js'],
parserOptions: {
project: null,
},
rules: {
'@typescript-eslint/await-thenable': 'off',
'@typescript-eslint/no-floating-promises': 'off',
},
},
],
};Or exclude specific directories entirely:
module.exports = {
ignorePatterns: ['dist/', 'build/', 'coverage/', '*.config.js'],
// ... rest of config
};After configuration changes, restart your development environment:
VS Code:
1. Press Cmd/Ctrl + Shift + P
2. Type "ESLint: Restart ESLint Server"
3. Press Enter
Or reload the window:
1. Press Cmd/Ctrl + Shift + P
2. Type "Developer: Reload Window"
3. Press Enter
Command line:
Kill any running ESLint processes and re-run:
# Run ESLint manually to verify
npx eslint src/
# Or through npm scripts
npm run lintClear ESLint cache:
# Remove cached ESLint results
rm -rf node_modules/.cache/eslint
# Or use ESLint's cache flag
npx eslint . --cache-strategy content### projectService vs project
As of @typescript-eslint v8, projectService is the recommended option over project:
projectService advantages:
- Automatically discovers tsconfig.json files for each source file
- Better performance for large monorepos
- Simpler configuration (just set to true)
- Works with project references automatically
project advantages:
- Explicit control over which tsconfig files are used
- Can specify multiple configs with glob patterns
- Better for complex setups where auto-discovery isn't desired
Migration from project to projectService:
// Old config (project)
parserOptions: {
project: ['./tsconfig.json', './packages/*/tsconfig.json'],
tsconfigRootDir: __dirname,
}
// New config (projectService)
parserOptions: {
projectService: true,
tsconfigRootDir: __dirname,
}### Performance Considerations
Type-aware linting is significantly slower than syntax-only linting because it requires TypeScript compilation:
Optimization strategies:
1. Use projectService instead of project - it's faster for incremental lints
2. Limit type-aware rules to specific files:
overrides: [
{
files: ['src/**/*.ts'],
extends: ['plugin:@typescript-eslint/recommended-type-checked'],
},
{
files: ['tests/**/*.ts'],
// Only use syntax rules for tests
extends: ['plugin:@typescript-eslint/recommended'],
},
]3. Enable ESLint caching:
npx eslint . --cache --cache-location node_modules/.cache/eslint4. In CI, consider splitting linting and type checking:
# Run type checking separately
npm run type-check # tsc --noEmit
# Run ESLint with only syntax rules
npm run lint:syntax### Troubleshooting Type Information Issues
Debug which tsconfig is being used:
Add this to see which tsconfig ESLint picks up:
parserOptions: {
projectService: {
allowDefaultProject: ['*.js'],
defaultProject: './tsconfig.json',
},
tsconfigRootDir: __dirname,
}Check if TypeScript can compile the file:
# If ESLint can't get types, verify TypeScript works
npx tsc --noEmit
# Trace module resolution
npx tsc --traceResolution | grep "yourfile.ts"Verify parser services are available:
Add a custom ESLint rule to debug:
// debug-rule.js
module.exports = {
rules: {
'debug-parser': {
create(context) {
const services = context.parserServices;
console.log('Has type checker:', !!services?.program);
return {};
},
},
},
};### Common Pitfalls
1. Creating default program (deprecated):
Old versions of @typescript-eslint allowed createDefaultProgram:
// DON'T USE - deprecated and slow
parserOptions: {
createDefaultProgram: true,
}This was removed in v6. Use projectService or ensure files are in your tsconfig instead.
2. Using workspace references incorrectly:
If you have TypeScript project references:
// tsconfig.json
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/utils" }
]
}Make sure your ESLint config points to the root tsconfig:
parserOptions: {
project: './tsconfig.json',
// This will follow references automatically
}3. Mixing ESM and CommonJS configs:
When using ESM (type: "module" in package.json), import paths in eslint.config.js matter:
// ESM flat config
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
export default [
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: __dirname,
},
},
},
];Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript