Skip to content

VSCode mixes import and require syntaxes on auto-import #29038

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

Closed
naoey opened this issue Dec 1, 2018 · 29 comments · Fixed by #32684, #35475, #36475 or #40879
Closed

VSCode mixes import and require syntaxes on auto-import #29038

naoey opened this issue Dec 1, 2018 · 29 comments · Fixed by #32684, #35475, #36475 or #40879
Assignees
Labels
Domain: TSServer Issues related to the TSServer Experience Enhancement Noncontroversial enhancements Fix Available A PR has been opened for this issue Suggestion An idea for TypeScript VS Code Priority Critical issues that VS Code needs fixed in the current TypeScript milestone

Comments

@naoey
Copy link

naoey commented Dec 1, 2018

In this particular instance I encountered the bug with moment.js.

  • VSCode Version: 1.30.0-insider, 1.29.1
  • OS Version: Windows 10 (1803), macOS 10.14.1

Steps to Reproduce:

  1. Begin typing usage of an un-imported module
  2. Press enter on auto-import intellisense suggestion

Does this issue occur when all extensions are disabled?: Yes

2018-12-01_12-15-51

Above recording is on fresh Insiders install with extensions disabled and being reproduced in a fresh project with just React and moment installed through yarn.

@mjbvz mjbvz transferred this issue from microsoft/vscode Dec 15, 2018
@mjbvz
Copy link
Contributor

mjbvz commented Dec 15, 2018

Tested with 3.3.0-dev.2018121. In a blank js file that is not part of any jsconfig project, moment is added as:

import moment = require('moment');

moment()

@mjbvz mjbvz removed their assignment Dec 15, 2018
@weswigham weswigham added Domain: TSServer Issues related to the TSServer Experience Enhancement Noncontroversial enhancements labels Dec 17, 2018
@weswigham
Copy link
Member

If esModuleInterop is on, we should probably prefer default imports over import =.

@DanielRosenwasser
Copy link
Member

Is that the ideal behavior, or current behavior?

@weswigham
Copy link
Member

Ideal, I believe

@jpike88
Copy link

jpike88 commented Jan 10, 2019

I have this issue too, but I don't have esModuleInterop on as it's not needed, I'm using es7 lib and esnext as target and module

@filipef101
Copy link

Any solution?

@jpike88
Copy link

jpike88 commented May 3, 2019

This is starting to drive me insane. Why is this even breaking like this? If a file has import statements, shouldn't the default auto-import behaviour stick to that?

@andrewbranch
Copy link
Member

You’re right. I think this particular scenario was left untouched because it was somewhat contentious—moment has a CommonJS export, and your particular settings allow neither a CommonJS import (import moment = require('moment')) nor a default import (import moment from 'moment'). And since moment is callable, import * as moment from 'moment' is technically incorrect (and is flagged as an error under --esModuleInterop). However, that one is the only one that TypeScript allows, and it will probably work at runtime too. So, it does seem like the obvious choice.

@SBRK
Copy link

SBRK commented Jan 27, 2020

@andrewbranch
It's still happening to me, with esModuleInterop = true so I'm guessing even though VSCode might not have your fix yet, it wouldn't make a difference. And it's not just in new files. In existing files with a ton of imports too. Most of the time it happens when auto importing lodash specific modules.
Ex: import size = require('lodash/size') instead of import size from 'lodash/size'.

Interestingly, if a file already has an import x from 'lodash/x', then subsequent auto imports will be correct.

EDIT: just tested with VSCode Insiders, and it's still happening

Version: 1.42.0-insider (user setup)
Commit: f3dbcea32a6b52ce819dc863e778fb8517357f61
Date: 2020-01-24T05:38:14.538Z
Electron: 7.1.7
Chrome: 78.0.3904.130
Node.js: 12.8.1
V8: 7.8.279.23-electron.0
OS: Windows_NT x64 10.0.17763

tsconfig.json:

{
  "compilerOptions": {
    "rootDirs": ["./src"],
    "outDir": "./dist",
    "lib": ["es7", "dom"],
    "moduleResolution": "node",
    "removeComments": true,
    "sourceMap": true,
    "declaration": false,
    "allowJs": true,
    "target": "es5",
    "module": "commonjs",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": false,
    "resolveJsonModule": true,
    "skipLibCheck": true
  },
  "files": ["./src/index.ts"],
  "exclude": [
    "node_modules"
  ]
}

Typescript version: 3.7.5

@andrewbranch
Copy link
Member

@SBRK I can’t reproduce this. The version of VS Code shouldn’t matter; only the version of TypeScript does. Can you use this extension to use the TS nightly and share either a repo or exact steps and file contents (including package.json) that trigger this behavior?

@SBRK
Copy link

SBRK commented Jan 27, 2020

Same problem with TS nightly. I will try to make a simple repro

@SBRK
Copy link

SBRK commented Jan 28, 2020

Hmm, I can't seem to get a simple repro workspace. Intellisense doesn't offer me to auto import lodash/size when I ctrl + space on size, unlike in my actual project.
I did use all the same devDependencies as in my project, but it doesn't behave the same...

@SBRK
Copy link

SBRK commented Jan 28, 2020

Ok I figured it out. It won't work unless it imports a file that itself imports lodash/size. This in itself seems like a problem. I don't know if it is the intended behaviour. Shouldn't anything that's in the dependencies (or that has its @types in devDependencies) be auto-importable ?

@andrewbranch here:
https://github.com/SBRK/vscode-import-problem
Just npm i, then open the workspace, open index.ts and try to auto import size

@SBRK
Copy link

SBRK commented Jan 28, 2020

Further cases that don't offer an autocomplete as expected (but that might be digression and need its own issue):
install moment to try these

  • create a .js file and type 'moment' => no autocomplete to import moment
  • create a function in that js file and in the function type moment => autocomplete offers you to import moment
  • in that same function, type lodash or size => no autocomplete for either lodash or size.
  • in that same function type _ => autocomplete to lodash but does not import anything.
  • in a .ts file, try to autocomplete moment in either top level or in a function => nothing

@derwaldgeist
Copy link

derwaldgeist commented Aug 18, 2020

This suddenly started to happen in my project without any modifications to my configuration. Instead of importing via import, I now get require statements. This is pretty annoying. How can I change this back? I am using ES6, not Typescript.

@andrewbranch
Copy link
Member

@derwaldgeist you’d have to give us a lot more detail about exactly how to reproduce your problem.

@marianovitale
Copy link

marianovitale commented Sep 1, 2020

Hi, this is happening to me with Enzyme. Instead of importing via import, I now get require statements.
I have not changed anything in my project. Also, like @derwaldgeist i am using ES6, not Typescript.
I have the latest version of vscode. I also have the latest version of "JavaScript and TypeScript Nightly" installed.

Any ideas?
Should I give more information?
example2

@andrewbranch
Copy link
Member

@Marianovh do you have a tsconfig.json or jsconfig.json file? Since this file doesn’t already have any imports or exports, and there’s (presumably) no config file that tells us that it can use ES6 imports, and the typings for enzyme didn’t indicate that the importing file specifically needed to use ES6 or CJS imports, we just had nothing to go on and defaulted to CJS. We could potentially look at more files in your program as a better heuristic. But an immediate fix would be to add a jsconfig.json file at the root of your repo with

{
  "compilerOptions": {
    "module": "es2015"
  }
}

@andrewbranch
Copy link
Member

andrewbranch commented Sep 1, 2020

Also, it should be noted that in any file that already has an ES6 import or export, it should do the right thing on future auto-imports in that file. If that’s not your experience, it’s a bug.

@marianovitale
Copy link

marianovitale commented Sep 2, 2020

@andrewbranch Thanks for your answer!
Creating a jsconfig.json file with the configuration you passed worked perfectly!.
Is there any reason why it take CJS as default? Can this be changed in an easy way?

Also, it should be noted that in any file that already has an ES6 import or export, it should do the right thing on future auto-imports in that file. If that’s not your experience, it’s a bug.

This is what happened, so it should not be a bug.

Anyway, thank you very much for your help.

@andrewbranch
Copy link
Member

Not a great one. require just works in more places right now. The LTS node release requires experimental flags to work with ESM, and bundlers do their own module loading and most of them will work with CJS or ESM with a seamless interop layer. The default could definitely change in the future, if we see CJS get phased out of the Node world.

@derwaldgeist
Copy link

you’d have to give us a lot more detail about exactly how to reproduce your problem.

To be honest, I don't have a clue what kind of information I could provide, but maybe this is just the wrong project to address this to (I came here via a Google search), since my problem is not directly related to TypeScript. I think, it's more a problem with the auto-import add-on itself. Sorry for bothering.

@andrewbranch
Copy link
Member

@derwaldgeist There’s no auto-import add-on; JavaScript support in VS Code is implemented by TypeScript. But it matters a lot what you were importing, what imports (if any) the file already imported, whether you have a tsconfig/jsconfig file in your project, and if so, what settings it has. I’m guessing your scenario was similar to @Marianovh’s, where your file didn’t have any imports/exports/requires yet. I don’t think it’s very expensive for us to examine other files in your project to get a better idea for a default. That would have fixed @Marianovh’s issue without needing to add a config file. I’ll reopen this issue to explore a solution like that.

@andrewbranch andrewbranch reopened this Sep 2, 2020
@derwaldgeist
Copy link

derwaldgeist commented Sep 3, 2020

@andrewbranch Thanks for the clarification. Well, at least for me, the biggest confusion was that everything worked perfectly - until all of a sudden auto-imports switched to require() statements instead of import statements. I never used any tsconfig / jsconfig files in my app, as I was not aware of them. I am using .eslintrc to configure things and (naively) assumed VSCode would use this config, too. Will try adding jsconfig now. I agree that parsing existing code is definitely not a good idea.

@nexsodev
Copy link

Same here. I not using Typescript nor have any config file, but after recent updates, auto import creates require statements instead ES6 import.
My current version is:

Version: 1.50.1 (system setup)
Commit: d2e414d9e4239a252d1ab117bd7067f125afd80a
Date: 2020-10-13T15:06:15.712Z
Electron: 9.2.1
Chrome: 83.0.4103.122
Node.js: 12.14.1
V8: 8.3.110.13-electron.0
OS: Windows_NT x64 10.0.18363

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