14

I'm working in an Angular 11 project. A lot of the imports in this project are using a relative path or an absolute path.

I have ESLint set-up for this project, I want to prevent relative import paths, and only allow absolute paths. But I'm not finding a rule to do this.
I've found: no-relative-parent-imports, but it's not giving me issues for paths like: import { HttpService } from "../http/http.service"; or import { RouterService } from "../../services/router/router.service"; (both are not absolute paths, the absolute paths for these would be import { HttpService } from "app/services/http/http.service"; and import { RouterService } from "app/services/router/router.service"; respectively.

I've read this article: https://medium.com/@aayush123/escaping-relative-import-hell-react-native-eslint-atom-57dc2cae5bcc
But I want to avoid adding another thing like Babel if I can avoid it.

Is there a rule for ESLint to prevent any type of relative paths? To only allow absolute paths?

ineedtoknow
  • 1,283
  • 5
  • 28
  • 46

6 Answers6

23

You can add eslint-no-restricted-imports to your .eslintrc file as follows:

"no-restricted-imports": ["error", {
  "patterns": [".*"]
}],

If there are some files where you need relative imports, you can add overrides to the eslint-config as follows:

"overrides": [
  {
    "files": ["*-test.js"],
    "rules": {
      "no-restricted-imports": "off"
    }
  }
]
GooDeeJAY
  • 1,681
  • 2
  • 20
  • 27
Keith Murgic
  • 347
  • 4
  • 8
  • I want this rule, but I also need my app to run. This rule helps highlight this as a problem: `import foo from './middleware/foo';`, and I can fix it and satisfy linting and VSCode error hightlighting, by removing `./`. Even CMD+right clicking opens the file in the IDE with the non-relative path! But, I goto run the app and get: _Error: Cannot find module 'middleware/foo'_ I've been trying to get non-relative paths implemented in-between other tasks for 3 weeks. Any insight? I did post a question, no responses. Feel like I've read half the internet to no avail. – Neil Gaetano Lindberg Dec 21 '21 at 17:27
  • 1
    @NeilGuyLindberg I was able to do this in a TypeScript CLI app by following the instructions here: https://bgxcode.com/posts/typescript/ts-absolute-import-paths/ . Now instead of `import foo from './middleware/foo';`, I have `import foo from '@app/middleware/foo';` where `@app` is an alias for my src base dir. – adashrod Dec 31 '21 at 22:18
  • Thank you @adashrod. I can use this method. However, I'm confused why I can do this in a JS project w/o \@app/, but I need to add that here? Like in the JS project I can just: `middleware/foo`... and the team is wanting the same. – Neil Gaetano Lindberg Jan 03 '22 at 16:19
5

Someone recently created a new ESLint rule specifically for your use case.

It supports fixing the issue for you and the option to allow parent folders.

Joel Bourbonnais
  • 2,618
  • 3
  • 27
  • 44
3

You can try my new plugin eslint-plugin-absolute-imports-only

...
settings: {
  "absolute-imports-only": {
    project: path.resolve(__dirname, 'tsconfig.json'),
  },
},
Thao Tang
  • 41
  • 5
2

In addition to the excellent answer here, I wanted to address how you can allow relative imports within the same directory but none further away. You can add this to the "rules" section of your eslint config file

"no-restricted-imports": [
  "error",
  {
    "patterns": ["^(?!\\.\\/)((?!.)[sS])*) ?$", "../.*"]
  }
]

This will allow relative imports within the same directory (e.g. ./somefile but disallows relative imports from any other level).

2

With the appropriate message:

{
  "no-restricted-imports": [
    "error",
    {
      "patterns": [
        {
          "group": ["./", "../"],
          "message": "Relative imports are not allowed."
        }
      ]
    }
  ]
}
Wenfang Du
  • 8,804
  • 9
  • 59
  • 90
1

I think the first regexp in this answer is invalid, but I couldn't really get the intention there, so I figured out a different way to allow only the current relative file but no deeper directories or other relative paths.

import A from '@/my/path'; // OK
import B from '/my/path'; // OK
import C from './my-file'; // OK (as it's in the same directory)
import D from './my/path/my-file'; // ERROR
import E from '../my/path'; // ERROR
import F from './../my/path'; // ERROR

I've also applied the appropriate message from here.

Final solution:

'no-restricted-imports': [
      'error',
      {
        patterns: [
          {
            group: ['./*/', '**../'],
            message: 'Relative imports are not allowed.',
          },
        ],
      },
    ],

NOTE: the regexp pattern of no-restricted-imports is actually an gitignore-style pattern.

Patrick L.
  • 15
  • 3