Search code examples
javascripttypescriptvisual-studio-codeeslinttsc

Eslint rule/Vscode setting to prevent importing folders without index


Question:

Is there an ESLint rule to enforce usage of */index on imports.

Example:

File structure:

utils/
   - index.js
   - a.js
   - b.js

main.js

main.js

// WRONG
import utils from "./utils";

// OK 
import utils from "./utils/index";

Why

I need this because my project is using tscpaths to replace absolute paths with relative paths after typescript compilation, but, for some reason, it doesn't replace when the */index is not present.

Alternative

If the rule doesn't exist, is there a vscode setting that would automatically add the index in auto imports?


Solution

  • Option 1, restructure your project so there are no index.js to import. The historic reason it is called index was to contain an index of the contents of that folder, to gather the typically exported things in a neat package so people don't have to look at the details within the folder. If that isn't what you need just don't call it index. You can probably just rename them all to main.js, mass find-replace the imports and future auto-imports from your IDE will work.

    Option 2, If there aren't too many folders where this is an issue you can write a config for no-internal-imports rule such that importing a folder by name is considered an "internal reference". This is probably the worst solution since there is no auto-fix and adding new folders requires updating the eslint config but this might be helpful to mention as an option

    Option 3, create a modified version of the no-useless-path-segments rule that does this, it currently has the opposite logic as you want so you would modify the code around lines 95-108 to check if the import isn't an index import but resolves to one suggest the fix:

    // assuming your rule has an option called enforceIndex
    if (options && options.enforceIndex && !regexUnnecessaryIndex.test(importPath)) {
        // if the import path is not pointing to an index file check if it resolves to a path that looks like an index file
        const resolved_path = resolve(importPath, context);
        if(regexUnnecessaryIndex.test(resolved_path)){
            // if the resolved_path resolves to something that looks like an index then suggest adding /index
            return reportWithProposedPath(`${importPath}/index`);
        }
    }
    

    But the fact that there is an eslint rule that imposes the exact opposite logic you want should be a decent indicator that what you are asking for is not exactly considered good form.