jquerynode.jstypescripttypescript1.6

Import jQuery in TypeScript 1.6.2 in Node.js


I'm working on a crawler using Node.js. I use jQuery for parsing pages built using jsdom.

I found a jquery.d.ts through tsd, which ends like this:

declare module "jquery" {
    export = $;
}
declare var jQuery: JQueryStatic;
declare var $: JQueryStatic;

This definition seems to be usable only on client side where jQuery is loaded globally or where a global window variable is available...

As explained here, when imported (using require) in an environment where window.document is not available (like Node.js), jQuery export a factory of itself which has to be initalized with a window object:

// JavaScript (ES5)
var jquery = require("jquery");
// ...
var $ = jquery(window);

But with TypeScript, since the definition doesn't contain this factory. It doesn't work:

// TypeScript
import jquery from "jquery"; // Module '"jquery"' has no default export
import {jquery} from "jquery" // Module '"jquery"' has no exported member 'jquery'
import {jQuery} from "jquery" // Module '"jquery"' has no exported member 'jQuery'
import {$} from "jquery" // Module '"jquery"' has no exported member '$'
import * as jquery from "jquery"; // Doesn't complain here, but `jquery` variable is not usable

I tried to write a definition of this factory, but it seems to not be as simple as I tought:

interface JQueryFactory {
    (window: any): JQueryStatic;
}

declare module "jquery" {
    export default JQueryFactory;
}
declare var jQuery: JQueryStatic;
declare var $: JQueryStatic;

And use it:

// TypeScript
/// <reference path="../../typings/tsd.d.ts"/>

import jquery from "jquery";
// ...
var $ = jquery(window); // error TS2304: Cannot find name 'jquery'

But now I have this strange error ?!


Solution

  • I answer to my question:

    I was very close, now, my jquery.d.ts ends like this:

    declare var jQuery: JQueryStatic;
    declare var $: JQueryStatic;
    declare function jQueryFactory (window: any): JQueryStatic;
    declare module "jquery" {
        export default jQueryFactory;
    }
    

    I didn't succeed to achieve this without declare the jQueryFactory function.

    As a small example, it can now basically be used like this :

    import {env}  from "jsdom";
    import jquery from "jquery";
    
    interface StuffInterface
    {
        title: string;
        text: string;
    }
    
    function parse (url: string): Promise<StuffInterface>
    {
        return new Promise((resolve, reject) => {
            env(url, (e, window) => {
                if (e) {
                    reject(e);
                    return;
                }
    
                var $ = jquery(window);
                var stuff = {
                    title: $('#stuff h1').text(),
                    text: $('#stuff .content').text()
                };
    
                resolve(stuff);
            });
        });
    }