angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.7k stars 11.98k forks source link

Compilation issue when I reference library from tsconfig.json "paths" attribute (regression from Angular 11 to 13) #22593

Closed cfeltz34 closed 2 years ago

cfeltz34 commented 2 years ago

🐞 Bug report

Command (mark with an x)

Is this a regression?

Yes, it's work on Angular 11. I just migrated my project to Angular 13 and it doesn't work anymore

Description

I develop a library independently of an application. The library and the application are therefore not in the same workspace. When I reference my library with npm, no problem. When I reference my library on tsconfig.json "paths" attribute, I have an error like "incompatible between types" (Angular 13 only)

🔬 Minimal Reproduction

On debug, to reference my library on my application I update the tsconfig.json file like this : "paths": { "my-library": [ "../MyLibrary/dist/my-library" ] My application have a class witch extends a class from my library. Both projects use the same version of @angular/common (13.1.3) (see on package.json and on node_modules folder). I compile my library project. I compile my application project. --> Exception with Angular 13

🔥 Exception or Error


Error: projects/Libs/apis-helpers/src/lib/services/apis-health-check/apis-health-check.service.ts:9:14 - error TS2415: Class 'ApisHealthCheckService' incorrectly extends base class 'HealthCheckService'.
  The types of 'http.http' are incompatible between these types.
    Type 'import("C:/Developpement/MyApplication/node_modules/@angular/common/http/http").HttpClient' is not assignable to type 'import("C:/Developpement/MyLibrary/node_modules/@angular/common/http/http").HttpClient'.

🌍 Your Environment

MyApplication tsconfig.json : 

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2020",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ],
    "skipLibCheck": true,
    "paths": {
      "angular-helpers": [
        "../../AngularHelpers/dist/angular-helpers"
      ]
    }
  }
}

package.json reference of @angular/common :

"@angular/common": "^13.1.3",

My Application angular.json file : 

      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/Example",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/manifest.json",
              "src/data",
              "src/is4-silent-refresh.html",
              "src/is4-redirect.html",
              "src/configs"
            ],
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "./node_modules/bootstrap/dist/css/bootstrap.min.css",
              "./node_modules/ngx-toastr/toastr.css",
              "src/app/styles/styles.scss"
            ],
            "budgets": [
              {
                "type": "anyComponentStyle",
                "maximumWarning": "6kb"
              }
            ],
            "scripts": [
              "./node_modules/jquery/dist/jquery.min.js",
              "./node_modules/bootstrap/dist/js/bootstrap.min.js"
            ]
          },
          "configurations": {
            "production": {
              ...
            },
            "development": {
              "aot": false,
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true,
              "assets": [
                "src/favicon.ico",
                "src/assets",
                "src/manifest.json",
                "src/data",
                "src/is4-silent-refresh.html",
                "src/is4-redirect.html",
                "src/configs/config.json",
                {
                  "input": "src/configs/development",
                  "output": "configs",
                  "glob": "*.json"
                }
              ]
            }
          },
          "defaultConfiguration": "development"
        },
cfeltz34 commented 2 years ago

Remark :

my angular.json file of my library is : 

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-helpers": {
      "projectType": "library",
      "root": "projects/Libs/angular-helpers",
      "sourceRoot": "projects/Libs/angular-helpers/src",
      "prefix": "frmk",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:ng-packagr",
          "options": {
            "tsConfig": "projects/Libs/angular-helpers/tsconfig.lib.json",
            "project": "projects/Libs/angular-helpers/ng-package.json"
          },
          "configurations": {
            "production": {
              "tsConfig": "projects/Libs/angular-helpers/tsconfig.lib.prod.json"
            }
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "projects/Libs/angular-helpers/src/test.ts",
            "tsConfig": "projects/Libs/angular-helpers/tsconfig.spec.json",
            "karmaConfig": "projects/Libs/angular-helpers/karma.conf.js"
          }
        },
        "lint": {
          "builder": "@angular-eslint/builder:lint",
          "options": {
            "lintFilePatterns": [
              "projects/Libs/angular-helpers/**/*.ts",
              "projects/Libs/angular-helpers/**/*.html"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "angular-helpers",
  "cli": {
    "analytics": false,
    "defaultCollection": "@angular-eslint/schematics"
  }
}
cfeltz34 commented 2 years ago

If I reference my library with command


npm i file:../MyLibrary/dist/angular-helpers
instead of "paths" attribute in tsconfig.json --> same issue
cfeltz34 commented 2 years ago

Angular CLI: 13.1.4
Node: 16.13.2
Package Manager: npm 8.1.2
OS: win32 x64

Angular: 13.1.3
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, router, service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1301.4
@angular-devkit/build-angular   13.1.4
@angular-devkit/core            13.1.4
@angular-devkit/schematics      13.1.4
@angular/cli                    13.1.4
@angular/flex-layout            13.0.0-beta.36
@schematics/angular             13.1.4
ng-packagr                      13.1.3
rxjs                            7.5.2
typescript                      4.5.5
alan-agius4 commented 2 years ago

Can you please share the package.json of your library?

cfeltz34 commented 2 years ago
{
  "name": "MyLibrary",
  "version": "0.0.2",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build-prod": "ng build --configuration production",
    "install-puppeteer": "cd node_modules/puppeteer && npm run install",
    "test": "npm run install-puppeteer && ng test --browsers=ChromeHeadless --watch=false --code-coverage",
    "lint": "ng lint --format=stylish",
    "e2e": "npm run install-puppeteer && ng e2e"
  },
  "private": false,
  "dependencies": {
    "@angular-devkit/build-angular": "^13.1.4",
    "@angular-devkit/core": "^13.1.4",
    "@angular-devkit/schematics": "^13.1.4",
    "@angular-material-components/datetime-picker": "^7.0.1",
    "@angular-material-components/moment-adapter": "^7.0.0",
    "@angular/animations": "^13.1.3",
    "@angular/cdk": "^13.1.3",
    "@angular/common": "^13.1.3",
    "@angular/compiler": "^13.1.3",
    "@angular/core": "^13.1.3",
    "@angular/flex-layout": "^13.0.0-beta.36",
    "@angular/forms": "^13.1.3",
    "@angular/material": "^13.1.3",
    "@angular/platform-browser": "^13.1.3",
    "@angular/platform-browser-dynamic": "^13.1.3",
    "@angular/router": "^13.1.3",
    "@angular/service-worker": "^13.1.3",
    "@microsoft/signalr": "^6.0.1",
    "@ngneat/until-destroy": "^9.0.0",
    "@swimlane/ngx-charts": "^20.0.1",
    "@typescript-eslint/eslint-plugin-tslint": "^5.10.1",
    "angular-hashtable": "0.2.1",
    "angular-oauth2-oidc": "^13.0.1",
    "core-js": "^3.20.3",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-jsdoc": "^37.6.3",
    "eslint-plugin-prefer-arrow": "^1.2.3",
    "flex-layout-srcs": "^5.0.0-beta.14",
    "jquery": "^3.6.0",
    "jspdf": "^2.5.0",
    "karma-coverage": "^2.1.0",
    "moment": "^2.29.1",
    "ngx-capture": "^0.12.1",
    "ngx-logger": "^5.0.7",
    "ngx-toastr": "^14.2.1",
    "rxjs": "^7.5.2",
    "tslib": "^2.3.1",
    "typescript-string-operations": "^1.4.1",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-eslint/builder": "13.0.1",
    "@angular-eslint/eslint-plugin": "13.0.1",
    "@angular-eslint/eslint-plugin-template": "13.0.1",
    "@angular-eslint/schematics": "13.0.1",
    "@angular-eslint/template-parser": "13.0.1",
    "@angular/cli": "^13.1.4",
    "@angular/compiler-cli": "^13.1.3",
    "@angular/language-service": "^13.1.3",
    "@schematics/angular": "^13.1.4",
    "@types/jasmine": "^3.10.3",
    "@types/jasminewd2": "^2.0.10",
    "@types/node": "^17.0.10",
    "@typescript-eslint/eslint-plugin": "5.3.0",
    "@typescript-eslint/parser": "5.3.0",
    "eslint": "^8.2.0",
    "jasmine-core": "~4.0.0",
    "jasmine-spec-reporter": "~7.0.0",
    "karma": "~6.3.11",
    "karma-chrome-launcher": "~3.1.0",
    "karma-jasmine": "~4.0.1",
    "karma-jasmine-html-reporter": "^1.7.0",
    "karma-junit-reporter": "^2.0.1",
    "karma-scss-preprocessor": "^4.0.0",
    "ng-packagr": "^13.1.3",
    "node-sass": "^7.0.1",
    "protractor": "~7.0.0",
    "puppeteer": "^13.1.1",
    "ts-node": "~10.4.0",
    "typescript": "~4.5.5"
  }
}
cfeltz34 commented 2 years ago

And package.json of my application :


{
  "name": "MyApplication",
  "version": "0.0.2",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build-prod": "ng build --configuration production",
    "install-puppeteer": "cd node_modules/puppeteer && npm run install",
    "test": "npm run install-puppeteer && ng test --browsers=ChromeHeadless --watch=false --code-coverage",
    "lint": "ng lint --format=stylish",
    "e2e": "npm run install-puppeteer && ng e2e"
  },
  "private": false,
  "dependencies": {
    "@angular-devkit/build-angular": "^13.1.4",
    "@angular-devkit/core": "^13.1.4",
    "@angular-devkit/schematics": "^13.1.4",
    "@angular-material-components/datetime-picker": "^7.0.1",
    "@angular-material-components/moment-adapter": "^7.0.0",
    "@angular/animations": "^13.1.3",
    "@angular/cdk": "^13.1.3",
    "@angular/common": "^13.1.3",
    "@angular/compiler": "^13.1.3",
    "@angular/core": "^13.1.3",
    "@angular/flex-layout": "^13.0.0-beta.36",
    "@angular/forms": "^13.1.3",
    "@angular/material": "^13.1.3",
    "@angular/platform-browser": "^13.1.3",
    "@angular/platform-browser-dynamic": "^13.1.3",
    "@angular/router": "^13.1.3",
    "@angular/service-worker": "^13.1.3",
    "@microsoft/signalr": "^6.0.1",
    "@ngneat/until-destroy": "^9.0.0",
    "@swimlane/ngx-charts": "^20.0.1",
    "@syncfusion/ej2-angular-inputs": "^19.4.43",
    "@typescript-eslint/eslint-plugin-tslint": "^5.10.1",
    "angular-hashtable": "0.2.1",
    "angular-helpers": "^0.0.2-20220128.1",
    "angular-oauth2-oidc": "^13.0.1",
    "bootstrap": "^3.4.1",
    "core-js": "^3.20.3",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-jsdoc": "^37.6.3",
    "eslint-plugin-prefer-arrow": "^1.2.3",
    "flex-layout-srcs": "^5.0.0-beta.14",
    "jquery": "^3.6.0",
    "jspdf": "^2.5.0",
    "karma-coverage": "^2.1.0",
    "moment": "^2.29.1",
    "ngx-capture": "^0.12.1",
    "ngx-logger": "^5.0.7",
    "ngx-toastr": "^14.2.1",
    "rxjs": "^7.5.2",
    "tslib": "^2.3.1",
    "typescript-string-operations": "^1.4.1",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-eslint/builder": "13.0.1",
    "@angular-eslint/eslint-plugin": "13.0.1",
    "@angular-eslint/eslint-plugin-template": "13.0.1",
    "@angular-eslint/schematics": "13.0.1",
    "@angular-eslint/template-parser": "13.0.1",
    "@angular/cli": "^13.1.4",
    "@angular/compiler-cli": "^13.1.3",
    "@angular/language-service": "^13.1.3",
    "@schematics/angular": "^13.1.4",
    "@types/jasmine": "^3.10.3",
    "@types/jasminewd2": "^2.0.10",
    "@types/node": "^17.0.10",
    "@typescript-eslint/eslint-plugin": "5.3.0",
    "@typescript-eslint/parser": "5.3.0",
    "eslint": "^8.2.0",
    "jasmine-core": "~4.0.0",
    "jasmine-spec-reporter": "~7.0.0",
    "karma": "~6.3.11",
    "karma-chrome-launcher": "~3.1.0",
    "karma-jasmine": "~4.0.1",
    "karma-jasmine-html-reporter": "^1.7.0",
    "karma-junit-reporter": "^2.0.1",
    "karma-scss-preprocessor": "^4.0.0",
    "ng-packagr": "^13.1.3",
    "node-sass": "^7.0.1",
    "protractor": "~7.0.0",
    "puppeteer": "^13.1.1",
    "ts-node": "~10.4.0",
    "typescript": "~4.5.5"
  }
}
alan-agius4 commented 2 years ago

The reason why this is failing when you install your library when using npm i because your library has incorrectly configured dependencies, which causes multiple @angular/ packages to be present in the node_modules tree.

Typically in a library you want to avoid having direct dependencies. Libraries that are required for the library to work, such as rxjs, @angular/x etc.. should be listed as peerDependencies, while other dependencies that are needed to build your library such as @angular-devkit/build-angular, karma-coverage etc... should be listed as devDependency.

While developing a library, you must install all peer dependencies through devDependencies to ensure that the library compiles properly. A linked library through path mappings has its own set of Angular libraries that it uses for building, located in its node_modules tree.

To get around this problem use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location. List all the peer dependencies that your library uses in the workspace TypeScript configuration file ./tsconfig.json, and point them at the local copy in the application's node_modules folder.

{
  "compilerOptions": {
    // ...
    // paths are relative to `baseUrl` path.
    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ]
    }
  }
}

This mapping ensures that your library always loads the local copies of the modules it needs.

Closing as this issue tracker is not suitable for support requests, please repost your issue on StackOverflow using tag angular-cli.

If you are wondering why we don't resolve support issues via the issue tracker, please check out this explanation.

angular-automatic-lock-bot[bot] commented 2 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.