Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Importing jqueryui with Typescript and RequireJS

I've been having trouble getting jQueryUI work properly. Before I tried to add jQueryUI, having jQuery alone worked just fine.

With the code below, I currently get "TypeError: jQuery is not a function(...)" in chrome, which is strange, considering that jquery is marked as a dependency in the require.config file.

The compiling from .ts to .js happens with no errors.

initApp.ts:

/// <reference path="../../../typings/jqueryui/jqueryui.d.ts"/>
import * as jQuery from "jquery"; //Works completely fine
import * as jQueryUI from "jquery-ui"; //Can't even find the module unless
                                       //d.ts file is modified

Compiled to js:

define(["require", "exports", "jquery-ui"], function (require, exports, jQuery) {...}

jqueryui.d.ts:

/// <reference path="../jquery/jquery.d.ts"/>
declare module JQueryUI { <unmodified code>}

//Added this declare

declare module "jquery-ui" {
  export = jQuery;
}

Require.config.js:

require.config({
    baseUrl: "./components/",
    paths: {
        "jquery": "./javascripts/lib/jquery-2.1.4",
        "jquery-ui": "./javascripts/lib/jquery-ui",
        "go": "./javascripts/lib/go-debug"
    },
    shim: {
        "jquery": {
          exports: "jQuery",
        },
        "jquery-ui": {
            //exports: "jQuery", //Adding this line doesn't fix the problem
            deps: ["jquery"],
        }
    },
});
require(["./javascripts/initApp"]);

Directory Tree:

typings/
    jquery/
        jquery.d.ts
    jqueryui/
        jqueryui.d.ts
web/
    components/
        javascripts/
            lib/
                jquery-2.1.4.js
                jquery-ui.js
                require.js
            initApp.js
            initApp.ts
            require.config.js

Links to full d.ts files:

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/jquery/index.d.ts (jquery V3.3)

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/jqueryui/index.d.ts (QueryUI V1.12)

Any help would be greatly appreciated

like image 390
Hackily Avatar asked Feb 11 '16 17:02

Hackily


2 Answers

So what happens is that you have jQuery which has an export, and jQueryUi which imports jQuery, augments it, and then exports $.widget not $.

This is why, as I think you already pointed out,

import * as jQuery from 'jquery-ui';

is problematic.

As you go on to note,

import jQueryUi from 'jquery-ui';

Does not work because jQueryUi is never used in a value position and so it gets elided by the compiler, which is actually really useful, if tricky, behavior that can make a number of asynchronous loading scenarios easier.

What you need is a way to tell TypeScript to perform an import of the library regardless of whether or not it is actually used, that is to say, we are importing it for its side effects.

Fortunately, ECMAScript has an import form which is provided specifically for this scenario. By writing

import 'jquery-ui';

you indicate that you depend on 'jquery-ui' for its side effects.

Furthermore, you do not need the shims for jQuery these days (don't quote me on this, my AMD is rusty).

So you should only need the following.

import $ from 'jquery';
// typescript will not remove this as the point of this syntax is: import for side-effects!
import 'jquery-ui';

You should not need to modify your require.config(....), but I could be misreading it.

Also, note the jquery-ui declarations, which you should probably update (your link was dead due to package restructuring) does not declare an exports and references jQuery as a global which sucks and messes up multi-version .d.ts scenarios, but should not make a practical runtime difference in your case.

like image 77
Aluan Haddad Avatar answered Oct 27 '22 04:10

Aluan Haddad


I also ran into this problem. After reading several of these questions where the answers were fairly muddled, I came up with the following:

including reference paths at the top of each file will solve this problem. No other changes needed. TS just needs to know where to find the definition files that describes all the functions that are available. Including a direct ref in each file solves that problem:

/// <reference path="/typings/jquery.d.ts"/>
/// <reference path="/typings/someotherlibrary.d.ts"/>

I could not get other methods mentioned to properly resolve. (I presume I am just stupid, but there could be bugs in the code or changing syntax in the APIs) If you have large numbers of files to resolve, this approach might not be the best solution.

like image 35
Roger Hill Avatar answered Oct 27 '22 02:10

Roger Hill