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

Exclude specific files from auto import suggestions #35395

Closed
5 tasks done
thorn0 opened this issue Nov 27, 2019 · 57 comments · Fixed by #49578
Closed
5 tasks done

Exclude specific files from auto import suggestions #35395

thorn0 opened this issue Nov 27, 2019 · 57 comments · Fixed by #49578
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Suggestion An idea for TypeScript

Comments

@thorn0
Copy link

thorn0 commented Nov 27, 2019

Search Terms

autoimport, exclude, ignore, isolation, encapsulation

Suggestion

We need a way to exclude files from auto import. Not from the project, only from the auto import suggestions.

Use Cases

My project includes a .d.ts file (generated from the previous version of the project) with legacy data structures (interfaces), many of which have the same names as their counterparts, newer data structures. As that file uses declare module "..." { ... } syntax, imports from it are non-relative, which is why auto import gives them a higher priority whereas modules with the newer structures have relative paths. The result is that the 'Add all missing imports' command constantly creates lots of wrong imports. If only there were a way to suppress suggestions for that specific module. I want to import from it only in rare cases.

I feel like this problem kind of defeats one of the important points of modules: I wanted to isolate those legacy definitions inside their module and forget about them, but because of this auto import issue they constantly get in the way.


Another example. Type definitions for libraries are in no hurry to use the new asserts feature of TS 3.7 for compatibility reasons. When I defined my own assert function to benefit from this feature, VS Code started to insist on importing assert form Node's console module instead, so, for lack of a better solution, I ended up renaming the function.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Dec 10, 2019
@raijinsetsu
Copy link

We have a similar issue in a large project: a legacy set of code that no new code should reference but which must stay where it is for compatibility. Being able to instruct VSCode to ignore the files in that folder for the purposes of auto-import would be VERY beneficial.

Currently, we're looking into whether or not ESLint can at least cause an error but I'm not sure it supports restricting relative modules like that.

@SimpleCookie
Copy link

I would also love to be able to exclude certain files. In my case I need a certain CSS file included AFTER another, however the organizeImports config automatically sorts them in the wrong order.

@yuval-gilboa
Copy link

An additional use case we have is to enable splitting implementation of a large namespace to multiple module files but still expose it under a single namespace. This would allow us to have better control over shape of exposed apis without being tied to the internal module structure we use.

For example, assuming we have three module files:

module1
module2
module3

We then define a re-exports module like this:

import * as module1 from './module1';
import * as module2 from './module2';
import * as module3 from './module3';

export const lib = { ...module1, ...module2, ...module3};

We then use the lib namespace to access all members of module1...3. But the members of these internal modules are also exposed on the global 'namespace' which pollutes the api surface. This cannot be avoided due to the way the module system works, but if we were able to exclude these files from intellisense auto-import it would make them practically hidden and thus partially solve our problem.

@uhyo
Copy link
Contributor

uhyo commented Aug 28, 2020

I also would love to see this feature.
I recently created a library named rocon and it has react.d.ts at the root directory so that users can import stuff from "rocon/react". The react.d.ts reexports everything from ./lib/react.

The problem is that TypeScript's auto-import suggestion prioritizes importing from rocon/lib/react rather than rocon/react. So it would be nice to exclude files inslide rocon/lib from the suggestion.

@IanEdington
Copy link

@RyanCavanaugh It looks like this ticket generated quite a bit of feedback since you added that label. Is there any other specific feedback you're looking for?

@RyanCavanaugh
Copy link
Member

I liked the prior comment's example of a real-life file layout that caused problems.

@richardbarrell-calvium
Copy link

I have a different use-case for asking for the same (or perhaps a different, but very similar) feature.

I have a codebase which uses a couple of libraries which have thousands of types defined in them (e.g. the "aws-sdk" library has, by my count, 28MB of ".d.ts" files). These libraries are only used in a couple of places in this codebase. It appears that their entire contents get considered for auto-suggestion everywhere. I believe this makes IDEs misbehave (I see VS Code spends >500ms in JSON.parse(), I'm told that IntelliJ exhibits weird behaviour) when typescript sends the IDE a big auto-complete candidate list.

Since I only use those libraries directly in a handful of files, it would be very useful to be able to omit them from typescript's auto suggestions. It would be even more useful to be able to turn auto suggest for them back on in just the specific files where I do want to use them.

As a workaround, I'm considering splitting my project into multiple packages (in one repo) so that the main top-level package doesn't have a direct dependency on the big libraries & their types aren't visible in it.

@richardbarrell-calvium
Copy link

richardbarrell-calvium commented Feb 17, 2021

I have a different use-case for asking for the same (or perhaps a different, but very similar) feature.
...snip

Issue #32174 looks like it's describing the same performance problem that I'm having & I'm looking for a way to work around. (FWIW I personally don't view it as a bug: expecting an analysis tool to be fast when feeding it 28MB of .d.ts files seems unreasonable to me, so I'd be ecstatic with a workaround for it rather than a "fix".)

@alarbada
Copy link

Disabling autoimports with "typescript.suggest.autoImports" does fine for me, as the Quick fix functionality does the auto importing well enough, even though it would be nice to be able to exclude some folder paths to improve perfomance.

@Glandos
Copy link

Glandos commented Jun 28, 2021

I have a Vue application with a main.ts:

import Vue from 'vue'

import './plugins/logger'
import './plugins/axios'

import App from './App.vue'
import router from './router'
import store from './store'
import i18n from './i18n'

// Auth needs axios and vuex (in store) defined
import './plugins/auth'
import vuetify from './plugins/vuetify'

// Make sure to register before importing any components
import './class-component-hooks'

import './plugins/caches'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  vuetify,
  i18n,
  render: h => h(App)
}).$mount('#app')

I am using a code action on save to organize imports automatically. On this very file, I have:

import Vue from 'vue'
import App from './App.vue'
// Make sure to register before importing any components
import './class-component-hooks'
import i18n from './i18n'
// Auth needs axios and vuex (in store) defined
import './plugins/auth'
import './plugins/axios'
import './plugins/caches'
import './plugins/logger'
import vuetify from './plugins/vuetify'
import router from './router'
import store from './store'






Vue.config.productionTip = false

new Vue({
  router,
  store,
  vuetify,
  i18n,
  render: h => h(App)
}).$mount('#app')

As you can see, the import order is now wrong, since auth is imported before axios.

Organize Imports is a very good features, especially on save, but I need to exclude this specific file from it. Even an inline comment could do the trick.

@posva
Copy link

posva commented Aug 11, 2021

This would be really useful for Vue as some libraries use an intermediate package in order to support Vue 2 and Vue 3 at the same time. The package is named vue-demi and is used by the libraries, but never in the application. So when people are using libraries using vue-demi (which points to either Vue 3 or Vue 2 depending on the installed dependencies), the auto-import features automatically adds import { ref } from 'vue-demi' instead of the corresponding import { ref } from 'vue' or import { ref } from '@vue/composition-api'. This is very easy to overlook and can cause very subtle and hard to debug issues.

Given the existing options of typescript.preferences.import... and some others, maybe there could be an option typescript.preferences.excludeAutoImports: string[] that exclude paths and package names. Maybe even a glob if that even makes sense but I think ignoring a whole folder would be enough.

@fgarcia
Copy link

fgarcia commented Aug 16, 2021

Maybe the exports keyword from packages.json is not a propper standard yet despite being widely supported, but it could be used as guideline of the preferred import path.

Whenever I want to import {Logger} from my @app/core/logs package within {repo}/packages/core I am suggested imports from

  • '../../core/src/logs'
  • '../../core/build/logs'
  • '../../core/dist/logs'
  • '../node_modules/@app/core/logs'

Would it be so strange looking into /packages/core/package.json and guess I just want this?

  • `@app/core/logs'

Currently it is not even suggested. I would even argue that any relative import that pass by a folder with a package.json file should be removed from the list of suggestions.

@vincaslt
Copy link

@chakra-ui/react is facing the same issue, it's reexporting everything, but autocomplete prefers direct imports from @chakra-ui/button etc.

aki77 added a commit to aki77/typescript-plugin-import-filter that referenced this issue Sep 12, 2021
@Dids
Copy link

Dids commented Sep 22, 2021

Vue 3 project here and the problem in my case is yup.

It exports types that clash with practically all primitive types, so if I want to define string as a type, VSCode will auto-import/suggest string from yup, not the default string type.

Been Googling this issue for hours, but so far haven't found a solution outside of getting completely rid of yup.

@HaveSpacesuit
Copy link

This has become an issue in the last few weeks that did not use to occur. If I try to auto import standard React functions or types, the default suggestion is coming from a different folder in node_modules. This consistently breaks my build and always takes me a minute to figure out. I would love to be able to add 'react-transition-group' to a blocked auto import list.

image

@andrewbranch
Copy link
Member

@HaveSpacesuit that's #45784, fixed by #45792

@andrewbranch
Copy link
Member

@Dids can you open a new issue for your problem? I believe globals are supposed to prevent auto-imports of the same name from showing up at all, but the rules around this have changed a couple times. It’s worth looking into though.

As a general rule, if auto-imports is doing something that objectively makes no sense, please file a new issue instead of commenting on this one for better visibility. This thread is about excluding things that we really have no way of knowing to exclude without the user telling us explicitly, like #35395 (comment). Thanks!

lgarron added a commit to cubing/cubing.js that referenced this issue Jan 5, 2022
…t autocompletions from dist.

This is a workaround to prevent a regression for microsoft/TypeScript#47184
If microsoft/TypeScript#35395 (Exclude specific files from auto import suggestions) is implemented, we should just use that instead.
lgarron added a commit to cubing/cubing.js that referenced this issue Jan 5, 2022
…t autocompletions from dist.

This is a workaround to prevent a regression for microsoft/TypeScript#47184
If microsoft/TypeScript#35395 (Exclude specific files from auto import suggestions) is implemented, we should just use that instead.
lgarron added a commit to cubing/cubing.js that referenced this issue Jan 5, 2022
…t autocompletions from dist.

This is a workaround to prevent a regression for microsoft/TypeScript#47184
If microsoft/TypeScript#35395 (Exclude specific files from auto import suggestions) is implemented, we should just use that instead.
lgarron added a commit to cubing/cubing.js that referenced this issue Jan 5, 2022
…t autocompletions from dist.

This is a workaround to prevent a regression for microsoft/TypeScript#47184
If microsoft/TypeScript#35395 (Exclude specific files from auto import suggestions) is implemented, we should just use that instead.
@oBusk
Copy link

oBusk commented Aug 2, 2022

@andrewbranch looks like it was done in microsoft/vscode#153160 correct?

@andrewbranch
Copy link
Member

Yes, my apologies; I forgot to message here as promised. This is available in typescript@next and VS Code now. #49578 explains how to use it. We’ll probably put something in the TypeScript release notes or the next VS Code release notes.

@fo-fo
Copy link

fo-fo commented Sep 4, 2022

This is all very cool, but now I find myself wanting to disable specific imports from libraries, while allowing others 🥴

First thing that comes to mind would be to make the autoImportFileExcludePatterns accept an object such as the following (a similar "set" pattern is already used in files.exclude in VSCode):

"autoImportFileExcludePatterns": {
  "someLib": {
    "default": true,
    "someExportedSymbol": true
  }
}

Any plans for something like this?

@acarroll-trend
Copy link

@fo-fo I 2nd that request. I would like it to stop suggesting

import { isEqual } from 'lodash-es';

and only allow

import isEqual from 'lodash-es/isEqual';

The former is very easy to accidentally select, and miss on review. The problem is that on our project, we lose tree shaking, and then the final bundle balloons. Sure, we could mitigate that in other ways, but this is the most elegant solution, IMO.

@zardoy
Copy link
Contributor

zardoy commented Dec 22, 2022

This is all very cool, but now I find myself wanting to disable specific imports from libraries, while allowing others 🥴

Hi, @fo-fo, @acarroll-trend and others, I made VS Code extension (essentially a TS plugin) that should satisfy your requests. Ignoring or changing sorting of import suggestions per symbol:

Configuration examples

To disable (ignore) specific imports from any module:

"tsEssentialPlugins.suggestions.ignoreAutoImports": [
    "path/*#resolve,join", // ignore resolve and join from `path` module and any subpaths of it
    "path/win32" // ignore all imports from this module specifically
],

#35395 (comment), It ensures these two imports will appear on top. For example when running Fix all missing imports quick fix, lodash-es/isEqual will be selected.

"tsEssentialPlugins.autoImport.changeSorting": {
    "isEqual": [
        // ensures these two will always be on top even if other libs are installed
        "lodash-es/isEqual",
        "lodash-es"
    ]
}

While it should work from quick fix, it doesn't work from autocomplete, because AFAIK reexports takes precedence in autocomplete, I can add a setting for that, but I'm not sure of format that would cover all cases.

@GabenGar
Copy link

@andrewbranch
How to use this feature in context of issue?
The situation is this:

  1. next-i18next imports useTranslation() from react-i18next in its type definitions.
  2. Creates a type alias off it.
  3. Then reexports useTranslation().
  4. The index file reexports useTranslation() from react-i18next.
    The result of all of this is next-i18next doesn't even appear in suggestions for useTranslation().

Let's say I have this project structure:

/project
  - frontend

Where frontend is the folder with nextjs project (and therefore next-i18next).
project is where the vscode workspace file is stored, which also defines project and /project/frontend as multi-roots of the workspace.
I've tried to put this snippet:

{
  "typescript.preferences.autoImportFileExcludePatterns": [
    "/**/node_modules/react-i18next"
  ]
}

In .vscode/settings.json in either/both of these folders and react-i18next is still in the autoimport suggestions. Am I right to assume this feature is not applicable because it's technically the same symbol spread across several files/packages? If so, how to make next-i18next at least appear in suggestions?

@andrewbranch
Copy link
Member

Am I right to assume this feature is not applicable because it's technically the same symbol spread across several files/packages?

That wasn’t the intention—it’s really just supposed to be individual files that are ignored. It sounds like that could be a bug.

Are react-i18next and next-i18next both listed as dependencies in your package.json in this case? Re-exports do tend to “shadow” their sources in completions, but I think that behavior should be disabled for cross-package re-exports.

@GabenGar
Copy link

Yes, the instructions say to install both of them.

@andrewbranch
Copy link
Member

@GabenGar would you mind opening a new bug to track this? I’ll take a look at both issues you mentioned.

@GabenGar
Copy link

@andrewbranch a bug? Isn't it like at least 3 (potential) bugs?

  • Cross-package re-exports of symbols.
    I also noticed it does sometimes show next-i18next or react-i18next in the autocompletion (but never both), so there might be a race condition involved.
  • that new feature of ignoring files/symbols/modules and it might or might not working due to issue above.
  • that new feature of ignoring files/symbols/modules and multi-root workspaces.
    I think for a start the first issue has to be resolved first, since others are dependent on it.

@andrewbranch
Copy link
Member

I don’t understand what your third bullet point means, but yes, there are two potential bugs. Feel free to open two separate ones if you prefer.

@GabenGar
Copy link

The path resolution rundown says this:

Relative paths will be resolved relative to the folder VS Code has opened.

What does it mean in context of multiroot workspaces, especially if it's in settings.json of .vscode folder of a given root?

@andrewbranch
Copy link
Member

It resolves relative to the “workspace folder” of the file being edited (vscode.workspace.getWorkspaceFolder). I’m not sure what that returns in a multi-root workspace, but it sounds like it would be the directory where the workspace file lives, not the root within the workspace. Which would make the relative paths specified inside individual roots unintuitive.

@0x80
Copy link

0x80 commented Mar 6, 2023

The current implementation doesn't cover nodejs built-in modules, right? The two that are bothering me the most are "assert" and "debug", but adding them to the config doesn't seem to have any effect.

These two wouldn't be a problem if there were a way to let TS always prefer functions from your own codebase over external modules. That may be easier to implement? Seems like a useful feature anyway. I don't know why you'd want to ever give priority to external modules when you have the same named functions within your codebase, so maybe it could even be default behavior...

The reason the built-in modules are messing things up is that I have functions named assert en log and the auto-imports default to getting them from those modules.

@andrewbranch
Copy link
Member

The current implementation doesn't cover nodejs built-in modules, right?

It does. You just have to specify filenames or globs that cover the file(s) where those ambient modules are declared (whatever shows up in Go To Definition on the module specifier).

Every time someone proposes a very reasonable sounding change to auto-import heuristics, we find that implementing it makes the experience worse for ~50% of people. When “local” modules are given priority, people in really large codebases get mad that Component gets auto-imported from "../../../../../apps/email-templating/external/__mocks/types/flux-capacitor" when they obviously meant to import from "react". It can definitely be worth revisiting these things from time to time, but my preference is to come up with solutions that don’t make zero-sum trades in sorting/priority.

@0x80
Copy link

0x80 commented Mar 8, 2023

@andrewbranch Awesome. For me, adding @types/node/assert.d.ts and @types/node/console.d.ts fixed my problem 👍

@0x80
Copy link

0x80 commented Mar 18, 2023

... but somehow it doesn't work for "log" coming from the debug module. Vscode points to "@types/node/debug/index.d.ts" but including it in the list of exclude patterns has no effect for me.

@andrewbranch
Copy link
Member

That file doesn’t exist in @types/node, so I’m not sure what you’re seeing.

@0x80
Copy link

0x80 commented Apr 2, 2023

@andrewbranch I got confused. It pointed to @types/debug, an external dependency. Everything seems to work fine after all 🎉

@oviniciusfeitosa
Copy link

oviniciusfeitosa commented Sep 20, 2023

  • Update your settings.json file:
"javascript.preferences.autoImportFileExcludePatterns": ["**/node_modules/@types/node/**"],
"typescript.preferences.autoImportFileExcludePatterns": ["**/node_modules/@types/node/**"],
  • Then reload your VSCode

@NazmusSayad
Copy link

I wanna exclude all the import suggestions from "data-fns".

{
  "typescript.preferences.autoImportFileExcludePatterns": [
    "date-fns",
    "**/date-fns",
    "**/date-fns/**",
    "**/date-fns/**/*",
    "node_modules/date-fns",
    "**/node_modules/date-fns",
    "**/node_modules/date-fns/**",
    "**/node_modules/date-fns/**/*"
  ],
  "javascript.preferences.autoImportFileExcludePatterns": [
    "date-fns",
    "**/date-fns",
    "**/date-fns/**",
    "**/date-fns/**/*",
    "node_modules/date-fns",
    "**/node_modules/date-fns",
    "**/node_modules/date-fns/**",
    "**/node_modules/date-fns/**/*"
  ]
}

I have tried these but still not working.

Typescript version: 5.3.2
VSCode version: 1.85.1
OS: Windows

@andrewbranch
Copy link
Member

Currently only workspace-relative paths (starting with ./ or ../) work on Windows. A fix is in progress.

@NazmusSayad
Copy link

Got it....

After using:

./**/node_modules/date-fns

It's working

@ev45ive
Copy link

ev45ive commented Feb 6, 2024

@andrewbranch This is great work. Very helpful. I can't figure out excluding built-ins though ?

typing log i get import {log} from "console" and console.log($0) snippet is next option, where import jest gets in the way
also typing beforeEach i get import {beforeEach} from "node:test" when I have vitest or jest already in imports

non of these work:

    "typescript.preferences.autoImportFileExcludePatterns": [
        "console",
        "node:test",
        "**/node_modules/@types/node/**",
        "./**/node_modules/console"
    ],

testing on Windows 10
VSCode 1.85.2
"typescript": "^5.2.2"

@andrewbranch
Copy link
Member

./**/node_modules/@types/node should do it. Also, leading with ./ shouldn’t be necessary by now if you’re using TypeScript nightly or VS Code Insiders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.