Avoiding relative paths in Angular CLI

Solution 1:

Per this comment, you can add your application source via paths in tsconfig.json:

{
  "compilerOptions": {
    ...,  
    "baseUrl": ".",
    "paths": {
      ...,
      "@app/*": ["app/*"],
      "@components/*": ["components/*"]
    }
  }
}

Then you can import absolutely from app/ or components/ instead of relative to the current file:

import {TextInputConfiguration} from "@components/configurations";

Note: baseUrl must be specified if paths is.

See also

  • https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

Solution 2:

Thanks to jonrsharpe's answer for pointing me in right direction. Although, after adding the paths, as defined in answer, I was still not able to make it work. For anyone else facing same problem as me in future, here's what I did to fix the issues.

I have a shared module and its services are being used in multiple components, so...

tsconfig.json:

{
    "compilerOptions": {
        ...
        "baseUrl": ".", //had to add this too
        "paths": {
            "@shared/*": ["src/app/modules/shared/*"]
        }
    }
}

After this, VS Code was able to resolve the import but I still got following error from webpack while compilation.

Module not found: Error: Can't resolve

To fix this I had to add

  1. baseUrl of tsconfig in webpack's resolve.modules
  2. paths of tsconfig in webpack's resolve.alias

webpack.config.js:

resolve: {
  extensions: ['*', '.js', '.ts'],
  modules: [
    rootDir,
    path.join(rootDir, 'node_modules')
  ],
  alias: {
    '@shared': 'src/app/modules/shared'
  }
},

component.ts:

import { FooService } from '@shared/services/foo.service'
import { BarService } from '@shared/services/bar.service'
import { BazService } from '@shared/services/baz.service'

To make it even more cleaner, I added an index.d.ts inside services folder and exported all my services from there, like this:

index.d.ts:

export * from './foo.service';
export * from './bar.service';
export * from './baz.service';

and now inside any component:

import { FooService, BarService, BazService } from '@shared/services';

Solution 3:

Above all answer correct, but after struggling by searching over internet n trying to understand what exactly problem and trying different troubleshooting option, I came to know baseUrl and Path how works toghether

If you use baseUrl:"." like below it works in VScode but not while compiling

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": ".",
    "paths": {
      "@myproject/*": ["src/app/*"]
    }    
}

As per my understanding and my working app and checked in angular aio code, I suggest use as baseUrl:"src" like below

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": "src",
    "paths": {
      "@myproject/*": ["app/*"],
      "testing/*": ["testing/*"]
    }    
}

By having base url as source(src directory), compiler properly resolves modules.

I hope this helps to people resolve this kind of issue.

Solution 4:

Not sure why but when I tried the other answers in VS2017, I was able to compile Angular without errors but I was still seeing errors in VS "Cannot find Module ...". When I set the baseUrl to "src" from "." everyone was happy.

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "baseUrl": "src",                 // Main source directory same level as tsconfig
    "paths": {
      "app/*": [ "app/*" ],           // src/app
      "ui/*": [ "ui/*" ],             // src/ui       
      "services/*": [ "services/*" ], // src/services
      "assests/*": [ "assests/*" ],     // src/assests
      "models/*": [ "models/*" ]      // src/models
    },
    "lib": [
      "es2017",
      "dom"
    ]
  }
}

Then to import:

import { AppMenuComponent } from 'ui/app-menu/app-menu.component';

Note: If Visual Studio is still throwing errors try either closing and reopening the file or restarting Visual Studio to get it to recognize the new paths.