Suggest jQuery import in TypeScript files

WebStorm smartly suggests all missing imports to be added with Alt+Enter in TypeScript files. It works well for all imports except for jQuery. Probably it assumes that all projects have jQuery/$ defined as a global variable, but it is not always true. Sometimes developers import jQuery as an ES6 module, and jQuery doesn't litter in the global namespace in this scenario. However, I didn't find a way to configure WebStorm to suggest such imports. Is it possible?

package.json:

{
  "dependencies": {
    "@types/jquery": "~3.5.0",
    "jquery": "~3.5.1",
    "typescript": "~3.9.6"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "outDir": "dist",
    "module": "commonjs",
    "target": "es6",
    "esModuleInterop": true
  },
  "include": [
    "src/**/*"
  ]
}

src/test.ts:

$(() => {
  console.log("Hello!");
});

Expected result: WebStorm suggests to add:

import $ from "jquery";

Actual result: No way to automate this import. The only way to proceed is to import it manually.

0
7 comments

Jquery module exposes $ as a global object that doesn't have to be imported; the IDE won't suggest auto-imports in such cases

0

That's what I said: jQuery DOESN'T expose $ global object if you import it as ES6 module, and that's exactly how we use it. We don't want to litter the global namespace. So, your response doesn't answer my question.

0

>jQuery DOESN'T expose $ global object

It does

With your setup, the code compiles fine without the import, doesn't it?

0

Elena, to save your time, I've prepared a minimal demo https://github.com/enepomnyaschih/jquery-test

Please use a modern browser to launch it, as it doesn't use Babel.

In src/with-import.ts, there's a jQuery import, so https://enepomnyaschih.github.io/jquery-test/with-import.html prints a proper "Hello!" message in console.

In src/no-import.ts, there's no jQuery import, so https://enepomnyaschih.github.io/jquery-test/no-import.html prints "Uncaught ReferenceError: $ is not defined" error in console.

The project uses Parcel for bundling, but with WebPack there would be no difference - I checked it. So this is the expected behaviour.

The clue is in these lines of jQuery code:

( function( global, factory ) {

"use strict";

if ( typeof module === "object" && typeof module.exports === "object" ) {

// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get jQuery.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info.
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}

// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

It works as follows:

  1. jQuery runs this function with `global` = `window` and `factory` = another function at the bottom.
  2. `if` check succeeds, because `module.exports` is indeed an object if jQuery is imported as an ES6 module.
  3. `global.document` exists, so the function assigns `module.exports = factory(global, true)`.
  4. True value in the 2nd argument is `noGlobal` flag which prevents jQuery from assigning a global $ variable.
  5. This way, jQuery DOESN'T expose a global variable.

Is it a sufficient explanation of my point? The only problem is that WebStorm doesn't suggest importing jQuery in src/no-import.ts.

Please don't suggest adding a <script> tag with jQuery - I don't want to return to 2012. We have ES6 modules now, and I want to use them for all libraries that support this syntax.

0

The IDE can't know how the app will be built and run; $ can be resolved without import due to a way it's defined in Typescript definition files, and thus is not suggested for importing.

0

Ok, so likely this is a problem of the TypeScript definition files. I hoped that there is a way to configure it somehow in WebStorm project settings. Thank you.

0

I found out that this issue occurs very often, and not only with jQuery. TypeScript definition files of TypeScript itself, WebPack, jQuery and other libraries contain global definitions of a wide variety of interfaces with very common names. For example: Account, Algorithm, Event, Map etc. These definition files severely clutter global namespace, so WebStorm doesn't suggest importing other interfaces with the same names from other files. This is very annoying. It would be really nice if WebStorm had a way to auto-import interfaces from other files even if an interface with the same name is present in type definition files of some libraries.

0

Please sign in to leave a comment.