Skip to content

jQuery type definitions are automatically included #22016

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
yvbeek opened this issue Feb 17, 2018 · 10 comments
Closed

jQuery type definitions are automatically included #22016

yvbeek opened this issue Feb 17, 2018 · 10 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@yvbeek
Copy link

yvbeek commented Feb 17, 2018

TypeScript Version: 2.7.2

Search Terms: types,jquery,implicit,import

Code

test.ts

$("body").html("Hello");

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "es6",
    "moduleResolution": "node",

    "sourceMap": true,
    "noEmit": true,
    "typeRoots": [],
    "types": [],

    "allowSyntheticDefaultImports": true,
    "allowUnusedLabels": true,
    "strictNullChecks": true
  },
  "compileOnSave": false,
  "typeAcquisition": {
    "enable": false,
  },
  "include": [
    "app/assets/javascripts"
  ]

Expected behavior:
$ and jQuery should be undefined.

I expect to have to import $:

import $ from "jquery";

Actual behavior:
The TypeScript compiler magically knows what $ and jQuery are without importing the types.

I don't want these types to be imported implicitly, that's why I'm setting types and typesRoots. But somehow the compiler does know what they are.

I've tried disabling this behavior in all kinds of ways, but I can't seem to fix it.

My package.json (I've removed a few irrelevant dependencies):

{
  "private": true,
  "dependencies": {
    "@rails/webpacker": "^3.2.2",
    "jquery": "^2.2.4",
    "jquery-ui": "^1.12.1",
    "jquery-ujs": "^1.2.2",
  },
  "devDependencies": {
    "@types/jquery": "^2.0.48",
    "@types/jqueryui": "^1.12.2",
    "ts-loader": "^3.5.0",
    "typescript": "^2.7.2",
    "webpack": "^3.11.0",
    "webpack-dev-server": "^2.11.1"
  }
}

I'm using the latest Visual Studio Code. My .vscode/settings.json instructs to use the bundled TypeScript version: { "typescript.tsdk": "node_modules/typescript/lib" }

@zspitz
Copy link
Contributor

zspitz commented Feb 17, 2018

Is this a VS Code issue? If you run the compiler from the command line, does it compile successfully?

tsc -p tsconfig.json

@yvbeek
Copy link
Author

yvbeek commented Feb 18, 2018

This is a TypeScript compiler issue.

It is compiling successfully but I want the compiler to fail if I don't do the proper jQuery import. The code shouldn't magically assume that jQuery is defined, I want it to be explicitly imported (like the other libraries I'm using).

  1. I have typeRoots set to an empty array
  2. I have types set to an empty array
  3. I'm not importing from "jquery" anywhere

To my knowledge the compiler shouldn't be able to resolve jQuery or $.

Eventually I want to remove jQuery from my project, so I would like to keep track where jQuery is being used.

@yvbeek
Copy link
Author

yvbeek commented Feb 18, 2018

I've created a small test application. It seems if I import jQuery in file A.ts, then it is also automatically available in file B.ts. Is that normal behavior?

@yortus
Copy link
Contributor

yortus commented Feb 18, 2018

@Zyphrax it's not a compiler problem, it's the way the types in jquery.d.ts are currently declared. The jquery typings include:

declare const jQuery: JQueryStatic;
declare const $: JQueryStatic;

These tell the TypeScript compiler that $ and jQuery are global variables. Once jquery.d.ts is included in the project's dependency graph, every file will 'see' $ and jQuery as globals.

It looks like jquery.d.ts is written the old way and needs some updating - it should export its types and values, instead of declaring them. But then that might break other people's code. I'm not a jquery user so I'm not sure what the best way forward is. But hopefully this at least sheds light on the problem you are seeing.

Looks like other people are also wanting to know how to do this: #12473.

@weswigham
Copy link
Member

weswigham commented Feb 18, 2018

Ideally it'd be written as a module and use export as namespace $; export as namespace jQuery; to make it available as a global in global contexts. But there's an issue: for real, jquery always patches itself onto the global scope. Like, unless you have a special build of jquery that's removed the global patching behavior, once it's run once, there will be a global $ and a global jQuery, even if loaded from a module.

@yvbeek
Copy link
Author

yvbeek commented Feb 18, 2018

Ah I see, thank you. I'm a bit confused though why you would ever want a global to apply to all .ts files. When I import something in file X, I expect it to only affect file X. Someone adding a class in the project could potentially change the way the rest of the project works, that sounds a bit scary.

@weswigham
Copy link
Member

Yep, and it's not a recommended way to build a package, for sure, but that's actually how jQuery works.

@yvbeek
Copy link
Author

yvbeek commented Feb 18, 2018

Would it perhaps be possible to have a compiler option to limit the scope of these globals? Or would that be a lot of work?

For now I might have a look at this: https://www.npmjs.com/package/jquery-ts

This makes me want to pull jQuery out of the project, but that is pushing it a bit for my next release 😄

@weswigham
Copy link
Member

It looks like (?) that package will still put the jQuery stuff in the globals, looking at it's source - it just doesn't report that in its type definitions. I'd personally not trust it, since if you accidentally include two conflicting jQuery versions, nothing will complain (when it probably should, since one will overwrite the other). The optimal solution is a custom jQuery build with exports/globals excluded and a modified definition file to remove the global declarations, I just don't know how feasible that'd be for you.

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Feb 23, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants