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 ?!
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);
});
});
}