Mono Repo: Accessing typescript file outside of project gives 'pos' undefined error

Viewed 580

I am trying to build an Angular mono repo. However, when I try to run lerna run start --scope=@demo/core-app I get the following error:

[error] TypeError: Cannot read property 'pos' of undefined
    at createFileDiagnosticAtReference (E:\Temp\node_modules\typescript\lib\typescript.js:107529:68)
    at addProgramDiagnosticAtRefPath (E:\Temp\node_modules\typescript\lib\typescript.js:107547:93)
    at checkSourceFilesBelongToPath (E:\Temp\node_modules\typescript\lib\typescript.js:107208:25)
    at Object.getCommonSourceDirectory (E:\Temp\node_modules\typescript\lib\typescript.js:105619:21)
    at Object.getDeclarationEmitOutputFilePath (E:\Temp\node_modules\typescript\lib\typescript.js:17179:125)
    at getOutputPathsFor (E:\Temp\node_modules\typescript\lib\typescript.js:99488:112)
    at forEachEmittedFile (E:\Temp\node_modules\typescript\lib\typescript.js:99425:41)
    at Object.emitFiles (E:\Temp\node_modules\typescript\lib\typescript.js:99654:9)
    at emitWorker (E:\Temp\node_modules\typescript\lib\typescript.js:106125:33)
    at E:\Temp\node_modules\typescript\lib\typescript.js:106102:72
    at runWithCancellationToken (E:\Temp\node_modules\typescript\lib\typescript.js:106205:24)
    at Object.emit (E:\Temp\node_modules\typescript\lib\typescript.js:106102:26)
    at getFileEmitOutput (E:\Temp\node_modules\typescript\lib\typescript.js:108003:26)
    at updateShapeSignature (E:\Temp\node_modules\typescript\lib\typescript.js:108239:36)
    at getFilesAffectedByUpdatedShapeWhenModuleEmit (E:\Temp\node_modules\typescript\lib\typescript.js:108442:46)
    at Object.getFilesAffectedBy (E:\Temp\node_modules\typescript\lib\typescript.js:108194:144)

Here's how the folder is structured with Lerna: (Example github repo - Link)

-- packages
   -- core-app (Angular project)
   -- shared (Shared project from where the angular project would utilize some types)

Root Level tsconfig.json

{
    "compilerOptions": {     
      "baseUrl": "./",      /* Enable incremental compilation */
      "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
      "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015',
      "strict": false,                           /* Enable all strict type-checking options. */
      // "esModuleInterop": true,                  
      "skipLibCheck": true,                     /* Skip type checking of declaration files. */
      "forceConsistentCasingInFileNames": true,  /* Disallow inconsistently-cased references to the same file. */
    },
    "references": [
      { "path": "packages/shared" },
      { "path": "packages/core-app" }
    ]
  }

Shared project tsconfig.json

{
    "extends": "../../tsconfig.json",
    "compileOnSave": false,
    "compilerOptions": {
      "baseUrl": "./",
      "outDir": "lib",
      "sourceMap": true,
      "downlevelIteration": true,
      "allowSyntheticDefaultImports": true,
      "experimentalDecorators": true,
      "module": "es2020",
      "moduleResolution": "node",
      "importHelpers": true,
      "declaration": true,
      "declarationMap": true,
      "lib": [
        "es2018",
        "dom"
      ],
      "composite": true,
      "paths": {
        "@demo/core-app/*": ["../core-app/src/*"],
        "@demo/shared/*": ["./src/*"]
      }
    },
    "references": [
      { "path": "../core-app" } 
    ]  
  }

Core-app (Angular) tsconfig.json

{
  "extends": "../../tsconfig.json",
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": true,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ],
    "composite": true,
    "paths": {
      "@demo/core-app/*": ["src/*"],
      "@demo/shared/*": ["../shared/src/*"]
    }
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  },
  "references": [
    { "path": "../shared" } 
  ]  
}
1 Answers

I think you don't need to add references and paths in tsconfig.json on both side, lerna should be able to do it for you after bootstrapping.

1. remove references, paths and composite in tsconfig.json

After you remove references and paths, you should be able to see a different error indicating the missing @demo/shared/models/ExampleModel module.

2. move the models folder in shared module

To have the exact path of @demo/shared/models/ExampleModel, move the models folder to the root level of shared module and remove src folder.

3. use interface or type for type definition. Otherwise, you will hit "Strict Class Initialization" error

shared/models/ExampleModel.ts

export interface ExampleModel{
    Id: number;
    Name: string;
}

4. add index.ts to export type for future expandability

shared/models/index.ts export * from './ExampleModel'

5. expose a entry point in shared module

In package.json, add main entry point

shared/package.json

{ "name": "@demo/shared", ... "main": "models/index.ts" }

6. add dev and peer dependencies of @demo/shared packages in core-app

core-app/package.json

"peerDependencies": {
    "@demo/shared": "^0.0.1"
},
"devDependencies": {
    ...
    @demo/shared": "^0.0.1",
    ...
    "typescript": "~4.1.5"
}

typescript should be below 4.2.0 for angular 11

7. fixing typo in app.component.html

should be examples instead of exmaples*

<div *ngFor="let example of examples"> 
  {{example.Name}}
</div>

8. boostraping

npx lerna bootstrap --hoist

9. run the app

npx lerna run start --scope=@demo/core-app

Here is the working repo for your reference. You can read the last commmit for details, it is concluded in the above steps.

Related