ESLint - Only Allow Absolute Import Paths Not Relative
Asked Answered
S

6

17

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?

Soninlaw answered 11/1, 2021 at 16:8 Comment(0)
B
29

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"
    }
  }
]
Backfield answered 12/1, 2021 at 12:51 Comment(3)
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.Wastepaper
@NeilGuyLindberg I was able to do this in a TypeScript CLI app by following the instructions here: 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.Plash
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.Wastepaper
D
9

With the appropriate message:

{
  "no-restricted-imports": [
    "error",
    {
      "patterns": [
        {
          "group": ["./", "../"],
          "message": "Relative imports are not allowed."
        }
      ]
    }
  ]
}
Deerdre answered 28/5, 2023 at 11:38 Comment(0)
M
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.

Mancilla answered 12/4, 2022 at 12:27 Comment(0)
Z
4

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).

Zoogeography answered 24/4, 2023 at 19:15 Comment(1)
This is great! Do you know how to make VScode to autoimport this way? I just asked this question here: #78695464Litharge
H
3

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

...
settings: {
  "absolute-imports-only": {
    project: path.resolve(__dirname, 'tsconfig.json'),
  },
},
Hagi answered 27/5, 2022 at 8:54 Comment(1)
This didn't work for me.Epsilon
C
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.

Crosswind answered 12/7, 2023 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.