Reputation: 208
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
Upvotes: 12
Views: 8519
Reputation: 31863
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.
Upvotes: 8
Reputation: 4118
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.
Upvotes: 1
Reputation: 729
I produced a little example on GitHub for using TypeScript 2 with ES 6 modules and JQuery / JQuery UI with custom plugins, I hope this will help: https://github.com/lgrignon/typescript-es6-jquery
Upvotes: 0
Reputation: 208
My initial workaround used to be embedded in the body of my question. I'm reposting it as an answer to meet StackOverflow's editorial guidelines.
Aluan's answer directly answers some of the questions I posed in this block.
I can manually fix the error by editing the compiled javascript to include both "jquery" and "jquery-ui" modules, and assigning them to variables:
define(["require", "exports", "jquery", "jquery-ui"], function (require, exports, jQuery, jQueryUI) {...}
However, I wanted the typescript compiler to automatically do this, or something similar to set both jquery-ui and jquery as dependencies of my file.
TypeScript takes the declared module name and compiles that string into the dependency parameters of the AMD define() function. Therefore, the TypeScript definition d.ts file must declare the module by the same string that represents my library in require.config.js
Simply having an import statement doesn't trigger any action from the TypeScript compiler. Whichever variable (foo, in this case) the properties from the module/library is imported into needs to be called at least once, and cannot conflict with any existing variables in that scope.
Earlier, I used this line:
import * as jQuery from "jquery-ui"
This occupied the 'jQuery' variable name, and thus, the jQuery function was no longer able to be assigned to that variable name, resulging in the error: "jQuery is not a function(...)"
As jquery-ui simply extends jQuery library, I never need call it. But the compiler got too smart on me and decided to not actually compile jquery-ui to be a dependency in my define(...). This was an easy fix once I realized the problem.
Final code
initApp.ts
/// <reference path="../../../typings/jqueryui/jqueryui.d.ts"/>
import * as jQueryUI from "jquery-ui";
import uiVar from "./uiVariables";
jQueryUI
Compiled to js:
define(["require", "exports", "jquery-ui"], function (require, exports, jQueryUI) {...}
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"
}
});
require(["./javascripts/app"]);
Upvotes: 0