Error when using JQueryUI with TypeScript and Defi

2019-04-06 09:00发布

问题:

So I'm trying to use JQueryUI with TypeScript and so far I've installed JQueryUI with npm install jquery-ui-dist and JQuery with npm install jquery. I've also added the definition files from DefinitelyTyped with npm install --save-dev @types/jquery and npm install --save-dev @types/jquery-ui.

I've got the following file (some parts omitted):

///<reference path="../../node_modules/@types/jqueryui/index.d.ts"/>
import * as $ from "jquery";
import "jquery-ui";

export default class Resizer {

    public static extraMargin = 5;

    public static setVerticalResizer(...) {
        ...
        let topElem: HTMLElement = <HTMLElement> cardElem.querySelector(".my-class");

        $(topElem).resizable({
            ...
        });
    }
}

And upon building and running I get the following error:

Uncaught TypeError: r(...).resizable is not a function

So I guess there's some problem with my way of importing JQueryUI? Or maybe JQueryUI was not installed correctly? Although the import and definitions seem to be working correctly in VS Code.

This is also how I'm using them in the HTML file:

<script src="node_modules/jquery-ui-dist/jquery-ui.mis.js"></script>
<link rel="stylesheet" href="node_modules/jquery-ui-dist/jquery-ui.min.css">

Any ideas on how to solve the problem and use JQueryUI with TypeScript?

回答1:

This is not a TypeScript error, this is a runtime error.

jQueryUI is actually being loaded twice!

Once via a script tag

<script src="node_modules/jquery-ui-dist/jquery-ui.mis.js"></script>

and then again in your module.

import $ from "jquery";
import "jquery-ui";

export default class ....

The code in the module above is correct, but the script tag is causing failure.

Additionally, I see that you have

///<reference path="../../node_modules/@types/jqueryui/index.d.ts"/>

Remove this! While it won't cause a runtime issue, that construct is for use when application code itself is written using globals, not modules.

If the types are not automatically picked up, either specify

"compilerOptions": {
  "moduleResolution": "node"
}

or use (shown with tsconfig.json next to node_modules)

"compilerOptions": {
  "baseUrl": ".", // required with paths but can be something besides "."
  "paths": {
    "jquery-ui": [
      "node_modules/@types/jqueryui/index"
    ]
  }
}


回答2:

Update: see working jsfiddle

So I guess there's some problem with my way of importing JQueryUI? Or maybe JQueryUI was not installed correctly? Although the import and definitions seem to be working correctly in VS Code.

It's a problem when compiling the typescript. The <script> tags aren't important for that.

When checking the jqueryui/index.d.ts, you could see resizable is defined there:

interface JQuery {
    ...

    resizable(): JQuery;
    resizable(methodName: 'destroy'): void;
    resizable(methodName: 'disable'): void;
    resizable(methodName: 'enable'): void;
    resizable(methodName: 'widget'): JQuery;
    resizable(methodName: string): JQuery;
    resizable(options: JQueryUI.ResizableOptions): JQuery;
    resizable(optionLiteral: string, optionName: string): any;
    resizable(optionLiteral: string, options: JQueryUI.ResizableOptions): any;
    resizable(optionLiteral: string, optionName: string, optionValue: any): JQuery;
    ... 
}

(See index.d.ts on GitHub)

and npm install --save-dev @types/jquery-ui.

There is no jquery-ui? It should be @types/jqueryui

After correctly installing the packages @/types/jquery-ui it works for me:

///<reference path="node_modules/@types/jqueryui/index.d.ts"/>

export default class Resizer {

    public static extraMargin = 5;

    public static setVerticalResizer() {

        var cardElem;
        let topElem: HTMLElement = <HTMLElement> cardElem.querySelector(".my-class");

        $(topElem).resizable({

        });
    }
}

In VS code:

Also from commandline, no errors and a javascript file is created (running from Powershell):

& "C:\Program Files (x86)\Microsoft SDKs\TypeScript\2.1\tsc.exe" .\test.ts

If is still not working, please share your tsconfig.json (if you have one) and the code and command how it doesn't compile