Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] Enforce internal/parent import order with alias #2540

Open
andreafspeziale opened this issue Sep 2, 2022 · 12 comments
Open

[question] Enforce internal/parent import order with alias #2540

andreafspeziale opened this issue Sep 2, 2022 · 12 comments

Comments

@andreafspeziale
Copy link

Hello!
I can't find a way to enforce import order to internal / parent using aliases. Maybe it is just not possible.

Example:

--- src
     |--- folderA
           |--- fileA1.ts
           |--- fileA2.ts
     |--- folderB
           |--- folderC
                 |--- fileC1.ts
           |--- fileB1.ts
           |--- fileB2.ts

Set an alias in my tsconfig.json

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

In fileC1.ts

import { foo } from '@src/folderA/fileA1'
import { bar } from '@src/folderB/fileB1'

I would really love to be able to enforce the import from B (parent) to happen after import A (internal) but I'm not sure it is possible since I believe that alias would "hide" it.

Thanks in advance!

@ljharb
Copy link
Member

ljharb commented Sep 2, 2022

I'm unclear on what you're asking. Wouldn't folderA and folderB both be internal?

@andreafspeziale
Copy link
Author

andreafspeziale commented Sep 2, 2022

Maybe I'm just totally wrong but based on my understanding being in fileC1.ts, file fileB1 is a parent and fileA1.ts is internal. So given a configuration like

'import/order': [
      2,
      {
        groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
        'newlines-between': 'never'
      },
    ],

I would like to enforce

import { bar } from '@src/folderB/fileB1' after import { foo } from '@src/folderA/fileA1'

With the above given config and (I believe) since I'm using alias the linter doesn't care about the order so:

import { bar } from '@src/folderB/fileB1'
import { foo } from '@src/folderA/fileA1'

is still valid.

@ljharb
Copy link
Member

ljharb commented Sep 2, 2022

oh right, you're in fileC at that point. Yes, folderB would be a parent and folderA would be internal.

So what you're saying is, you WANT them to be sorted so that folderA comes first (because it's internal), but because it's using a TS alias, it's recognizing it as a parent?

Can you share your eslint config? Hopefully you're using the TS eslint resolver.

@andreafspeziale
Copy link
Author

You got it! (btw I don't really know if it's folderA recognize as parent or is it viceversa - so it's folderB recognize as internal, what I know is that switching their order would not trigger any error)

eslintrc.js

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    sourceType: 'module',
    tsconfigRootDir: __dirname,
  },
  plugins: ['@typescript-eslint/eslint-plugin', 'unused-imports'],
  extends: [
    'plugin:@typescript-eslint/recommended',
    'plugin:import/recommended',
    'plugin:import/typescript',
    'plugin:prettier/recommended',
    "plugin:@dword-design/import-alias/recommended",
  ],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: ['.eslintrc.js'],
  rules: {
    '@typescript-eslint/explicit-function-return-type': 1,
    '@typescript-eslint/explicit-module-boundary-types': 0,
    '@typescript-eslint/no-explicit-any': 0,
    '@typescript-eslint/no-inferrable-types': 0,
    '@typescript-eslint/no-shadow': 1,
    '@typescript-eslint/no-unused-vars': [1, { ignoreRestSiblings: true }],
    'import/namespace': 0,
    'import/no-extraneous-dependencies': [2, { devDependencies: ['**/test/**'] }],
    'import/order': [
      2,
      {
        groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
        'newlines-between': 'never'
      },
    ],
    'lines-between-class-members': [2, 'always', { exceptAfterSingleLine: true }],
    'unused-imports/no-unused-imports': 2,
  },
  overrides: [
    {
      files: ['*.decorator.ts'],
      rules: {
        '@typescript-eslint/explicit-function-return-type': 0,
      },
    },
  ],
  settings: {
    'import/parsers': {
      '@typescript-eslint/parser': ['.ts', '.tsx'],
    },
    'import/resolver': {
      typescript: {
        alwaysTryTypes: true,
      },
    },
  },
};

@ljharb
Copy link
Member

ljharb commented Sep 2, 2022

cc @JounQin if the TS resolver is reporting @src/folderB/fileB1 as a parent instead of internal, there's not much the plugin can do, I think.

@JounQin
Copy link
Collaborator

JounQin commented Sep 22, 2022

cc @JounQin if the TS resolver is reporting @src/folderB/fileB1 as a parent instead of internal, there's not much the plugin can do, I think.

@ljharb Sorry I didn't notice the mention previously, but I'm not quite sure to understand why it's related to the TS resolver, does it resolve a incorrect absolute path?

@ljharb
Copy link
Member

ljharb commented Sep 22, 2022

I'm not certain, but it seems like it's resolving it as a relative path (a parent) rather than a bare specifier (in node_modules).

@JounQin
Copy link
Collaborator

JounQin commented Sep 22, 2022

@ljharb

I'm not certain, but it seems like it's resolving it as a relative path (a parent) rather than a bare specifier (in node_modules).

I'm still confused, it's using TS alias, and @src is not a bare specifier (in node_modules).

Besides, @andreafspeziale can you please provide a minimal reproduction?

@ljharb
Copy link
Member

ljharb commented Sep 22, 2022

Right, but a TS alias should still report as if it's npm linked in, i assume?

@JounQin
Copy link
Collaborator

JounQin commented Sep 22, 2022

@andreafspeziale Can you try DEBUG=eslint-import-resolver-typescript first to see what absolute paths are resolved?

Right, but a TS alias should still report as if it's npm linked in, i assume?

@ljharb I don't think that's possible, ts resolver returns absolute paths, it's not npm linked, is it?

@andreafspeziale
Copy link
Author

@JounQin Sure I'll try to ship a sample ASAP

@andreafspeziale
Copy link
Author

@JounQin @ljharb As promised.
https://github.com/andreafspeziale/eslint-issue-sample

So we can also be sure that the issue is not me messing-up something or just not understanding that it's simply not possible since aliases are "flattening" everything ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants