Failing to apply lint parserOptions.project pointing at project tsconfig.json after Angular migration

115 Views Asked by At

To migrate Angular 15 to Angular 16.2.x I also had to update devDependencies, including eslint from ~8.33.0 to ^8.39.0

Now I am receiving the error message:

You have attempted to use a lint rule which requires the full TypeScript type-checker to be available, but you do not have parserOptions.project configured to point at your project tsconfig.json files in the relevant TypeScript file "overrides" block of your project ESLint config for projectname

I have attempted to

  • disable the set rules for angular-eslint/template
  • explicitely set ./tsconfig.json in parserOptions.project

Folder structure:

  • projectname
    • frontend
      • src
      • .eslintrc.js
      • angular.json
      • package.json
      • tsconfig.json

The migration was successful but the linter fails in regards to a missing configuration, even though projects of parserOptions is configured to point at projectname's tsconfig file.

I have looked for breaking changes, but only the minor version updated

.eslintrc.js file

module.exports = {
  root: true,
  parserOptions: {
    project: [
      'src/tsconfig.json',
      'src/tsconfig.spec.json',
      'src/tsconfig.app.json'
    ],
    createDefaultProgram: true
  },
  plugins: ['@typescript-eslint', 'prettier'],
  ignorePatterns: ['**/node_modules/**', '.gradle/**', 'build/**', 'src/polyfills.ts', 'src/index.html'],
  extends: [
    'plugin:@angular-eslint/recommended',
    'plugin:@angular-eslint/template/process-inline-templates'
  ],
  rules: {
    '@angular-eslint/component-selector': [
      'error',
      {
        prefix: 'kebab-case',
        type: 'element'
      }
    ],
    '@angular-eslint/directive-selector': [
      'error',
      {
        prefix: 'kebab-case',
        type: 'attribute'
      }
    ],
    '@angular-eslint/use-lifecycle-interface': 'error',
    '@typescript-eslint/array-type': [
      'error',
      {
        default: 'array'
      }
    ],
    '@typescript-eslint/consistent-type-assertions': 'error',
    '@typescript-eslint/prefer-for-of': 'error',
    '@typescript-eslint/prefer-function-type': 'error',
    '@typescript-eslint/unified-signatures': 'error',
    'eqeqeq': ['error', 'always'],
    'guard-for-in': 'error',
    'id-denylist': ['error', 'any', 'Number', 'number', 'String', 'string', 'Boolean', 'boolean', 'Undefined', 'undefined'],
    'id-match': 'error',
    'new-parens': 'error',
    'no-caller': 'error',
    'no-eval': 'error',
    'no-new-wrappers': 'error',
    'no-throw-literal': 'error',
    'no-trailing-spaces': 'error',
    'no-undef-init': 'error',
    'no-var': 'error',
    'object-shorthand': 'error',
    'one-var': ['error', 'never'],
    'prefer-const': 'error',
    '@angular-eslint/component-class-suffix': 'error',
    '@typescript-eslint/no-unused-expressions': 'error',
    'no-bitwise': 'error',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/explicit-module-boundary-types': ['error', {allowArgumentsExplicitlyTypedAsAny: true}],
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/quotes': ['error', 'single', {avoidEscape: true, allowTemplateLiterals: true}]
  },
  overrides: [
    {
      files: ['*.component.html', 'src/index.html', 'src/'],
      extends: ['plugin:@angular-eslint/template/recommended'],
      plugins: ['@angular-eslint/template'],
      rules: {
        '@angular-eslint/template/cyclomatic-complexity': 'off',
        '@angular-eslint/template/no-call-expression': 'off',
        'spaced-comment': 'off'
      }
    }
  ]
}

package.json file

{
  "name": "projectname-frontend",
  "version": "0.0.0-SNAPSHOT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --project=projectname",
    "start:proxy:local": "ng serve --proxy-config proxy.conf.local.json --project=projectname",
    "build": "ng build --project=projectname",
    "test": "npm run lib:build && ng test --project=projectname",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~16.2.0",
    "@angular/cdk": "~16.2.0",
    "@angular/common": "~16.2.0",
    "@angular/compiler": "~16.2.0",
    "@angular/core": "~16.2.0",
    "@angular/forms": "~16.2.0",
    "@angular/localize": "~16.2.0",
    "@angular/material": "~16.2.0",
    "@angular/platform-browser": "~16.2.0",
    "@angular/platform-browser-dynamic": "~16.2.0",
    "@angular/router": "~16.2.0",
    "@fortawesome/fontawesome-pro": "6.3.0",
    "@ng-bootstrap/ng-bootstrap": "~15.1.2",
    "@popperjs/core": "~2.11.8",
    "bootstrap": "~5.2.3",
    "dwv": "0.28.1-2",
    "file-saver": "2.0.5",
    "rxjs": "~7.8.1",
    "tslib": "~2.6.2",
    "zone.js": "^0.13.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^16.2.0",
    "@angular-eslint/builder": "~16.2.0",
    "@angular-eslint/eslint-plugin": "~16.2.0",
    "@angular-eslint/eslint-plugin-template": "~16.2.0",
    "@angular-eslint/schematics": "~16.2.0",
    "@angular-eslint/template-parser": "~16.2.0",
    "@angular/cli": "~16.2.0",
    "@angular/compiler-cli": "~16.2.0",
    "@angular/language-service": "~16.2.0",
    "@types/file-saver": "~2.0.7",
    "@types/jasmine": "~5.1.2",
    "@types/jasminewd2": "~2.0.13",
    "@types/node": "~20.9.0",
    "@typescript-eslint/eslint-plugin": "^6.11.0",
    "@typescript-eslint/parser": "^6.11.0",
    "eslint": "^8.39.0",
    "eslint-config-prettier": "~9.0.0",
    "eslint-plugin-import": "~2.29.0",
    "eslint-plugin-jasmine": "~4.1.3",
    "eslint-plugin-prettier": "~5.0.1",
    "jasmine-core": "~5.1.1",
    "jasmine-spec-reporter": "~7.0.0",
    "json-server": "^0.17.4",
    "karma": "~6.4.2",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage-istanbul-reporter": "~3.0.3",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "karma-junit-reporter": "~2.0.1",
    "ng-packagr": "16.2.3",
    "shx": "~0.3.4",
    "ts-node": "~10.9.1",
    "typescript": "~4.9.5"
  }
}
1

There are 1 best solutions below

0
On

This may be apples and oranges, but our project had a similar problem and we chased it down to one particular rule that seemed to be causing what some might interpret as a false-positive error message. We also had what looked a perfectly valid definition of parserOptions.project prior to and and after the Angular 16 upgrade.

Still waiting on our project leads to determine if removing that rule altogether is viable.

"Bad" rule in question @typescript-eslint/naming-convention

For what it's worth: removing the rule is not necessary, you can just set the reporting level to "off" in case you want to circle back to it.

It may also be the case that other @typescript-eslint/* rules may be beyond end-of-support lifecycle for your project after the upgrade.

[Update] Across a fairly large code-base with several shared libraries, no other @typescript-eslint/* rules ended up needing to be deactivated.