eslint Angular Strict Template Checks should show error

Viewed 864

We recently migrated to a new project with many angular 11+ applications and libraries. We have angularCompilerOptions.strictTemplates: true set for all the applications.

The problem is that we have a CI pipeline that checks for formatting and runs eslint, but the strict template checks errors do not get flagged until we do a production build. because of this, we have to build all the affected apps in the CI, and if we change a library component all apps need to be checked and built. this can take hours.

Is there a way that eslint/tslint can check for any strict template errors without needing to build the app every time?

Here is our eslint.json:

{
  "extends": ["../../.eslintrc.json"],
  "ignorePatterns": ["!**/*"],
  "overrides": [
    {
      "files": ["*.ts"],
      "extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
      "parserOptions": { "project": ["apps/to-home/tsconfig.*?.json"] },
      "rules": {
        "@angular-eslint/directive-selector": ["error", { "type": "attribute", "prefix": "toh", "style": "camelCase" }],
        "@angular-eslint/component-selector": ["error", { "type": "element", "prefix": "toh", "style": "kebab-case" }]
      }
    },
    { "files": ["*.html"], "extends": ["plugin:@nrwl/nx/angular-template"], "rules": {} }
  ]
}

and the root json:

{
  "root": true,
  "ignorePatterns": ["**/*"],
  "plugins": ["@nrwl/nx"],
  "overrides": [
    {
      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
      "extends": [
        "plugin:@angular-eslint/recommended",
        "plugin:@angular-eslint/template/process-inline-templates",
        "plugin:prettier/recommended"
      ],
      "rules": {
        "@typescript-eslint/no-unused-vars": [
          "error",
          {
            "argsIgnorePattern": "^_"
          }
        ],
        "@typescript-eslint/no-empty-function": [
          "error",
          {
            "allow": ["constructors"]
          }
        ],
        "@nrwl/nx/enforce-module-boundaries": [
          "error",
          {
            "enforceBuildableLibDependency": true,
            "allow": [
              "@models/*",
              "@apc-common/**",
              "@apc-directives/**",
              "@apc-helpers/**",
              "@apc-modals/**",
              "@apc-models/**",
              "@apc-pipes/**",
              "@apc-services/**",
              "@apc-store/**",
              "@apc-admin/**",
              "@apc-help/**",
              "@apc-home/**",
              "@apc-materials/**",
              "@apc-materials-deferral-review/**",
              "@apc-parking/**",
              "@apc-report/**",
              "@apc-turnover/**",
              "@apc-wall-display/**",
              "@apc-workload/**"
            ],
            "depConstraints": [
              {
                "sourceTag": "scope:server",
                "onlyDependOnLibsWithTags": ["scope:server", "scope:models"]
              },
              {
                "sourceTag": "scope:ui",
                "onlyDependOnLibsWithTags": ["scope:ui", "scope:shared", "scope:models"]
              },
              {
                "sourceTag": "scope:shared",
                "onlyDependOnLibsWithTags": ["scope:shared", "scope:models"]
              },
              {
                "sourceTag": "scope:models",
                "onlyDependOnLibsWithTags": ["scope:models"]
              }
            ]
          }
        ],
        "@typescript-eslint/no-this-alias": [
          "error",
          {
            "allowDestructuring": true,
            "allowedNames": ["self"]
          }
        ]
      }
    },
    {
      "files": ["*.ts", "*.tsx"],
      "extends": ["plugin:@nrwl/nx/typescript"],
      "parserOptions": {
        "project": "./tsconfig.json"
      },
      "rules": {}
    },
    {
      "files": ["*.js", "*.jsx"],
      "extends": ["plugin:@nrwl/nx/javascript"],
      "rules": {}
    }
  ]
}

2 Answers

TypeScript strictly typed: strict mode is not enough, typescript-strictly-typed enables configurations for strictly typed TypeScript, ESLint or TSLint, and optionally Angular. But let’s explain first.

The officially recommended way to work with TypeScript is in strict mode.
Strict mode is enabled when creating:

  1. a TypeScript project (tsc --init)
  2. an Angular app in strict mode (ng new --strict)

Strict mode activates 2 main compiler options:
noImplicitAny

strictNullChecks

Now, TypeScript will ask to tell when a value can be null (strictNullChecks), and when inference is not possible it will ask the type (noImplicitAny).

The bellow code will compile, even in strict mode: explicit anys are still accepted by TypeScript

function test(hello: any, world = '') {
  hello; // any
  world; // string
}

TSLint has the no-any rule. With ESLint and @typescript-eslint no-explicit-any rule:

.eslintrc.json

{
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "@typescript-eslint"
  ],
  "rules": {
    "@typescript-eslint/no-explicit-any": "error"
  }
}

Angular strict:
Angular has its own additional strict compiler options:
tsconfig.json

{
  "angularCompilerOptions": {
    "strictInjectionParameters": true,
    "strictTemplates": true,
    "strictInputAccessModifiers": true
  }
}

We only had to run ng build to see this error with Angular 9 and upper. while in Angular 8 we did not see this error message when we ran ng build.

Automate configuration: Enables configurations for strictly typed TypeScript, ESLint or TSLint, and optionally Angular. Just run npx typescript-strictly-typed in your project.

Probably you don't have enabled aot on development environment. You may have aot=true only on production section of angular.json. To set it to all configurations, do this:

"architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
        "aot": true,
...
Related