admin管理员组文章数量:1336633
I have a number of jQuery plugins that I would like to load using the AMD pattern in TypeScript. For example, I might have this structure:
/lib/jquery.myplugin.js
/app.ts
The plugin simply extends jQuery. It provides no new top-level functions or variables. An example might be:
// jquery.myplugin.js
jQuery.fn.myExample = function() { ... }
The corresponding jquery.myplugin.d.ts file looks like:
interface JQuery {
myExample();
}
So that now in app.ts I can call something like $('#my-element').myExample()
. Note that this assumes I already have the jquery.d.ts declarations from Microsoft loaded.
My question is how do I load this library asynchronously and take advantage of TypeScripts static typing? I could use it like this:
/// <reference path="lib/jquery.myplugin.d.ts"/>
but that requires me to add a <script>
tag to my HTML, and the library is not loaded asynchronously. I want TypeScript to generate this code:
define(["require", "exports", "lib/jquery.myplugin"], function (require, exports, __jquery.myplugin__) {
...
// Use my plugin
$('#my-element').myExample();
}
However since there are no exports in the .d.ts file I can't write import myplugin = module('lib/jquery.myplugin')
.
The closest I've gotten is to make a jquery.myplugin.d.ts
that references another ts file with the interface declaration and includes at least one export. However there is nothing to export in this library, and in order to get the desired output I have to not only add an export but I have to call it.
Update: I have opened a work item for this on typescript.codeplex
I have a number of jQuery plugins that I would like to load using the AMD pattern in TypeScript. For example, I might have this structure:
/lib/jquery.myplugin.js
/app.ts
The plugin simply extends jQuery. It provides no new top-level functions or variables. An example might be:
// jquery.myplugin.js
jQuery.fn.myExample = function() { ... }
The corresponding jquery.myplugin.d.ts file looks like:
interface JQuery {
myExample();
}
So that now in app.ts I can call something like $('#my-element').myExample()
. Note that this assumes I already have the jquery.d.ts declarations from Microsoft loaded.
My question is how do I load this library asynchronously and take advantage of TypeScripts static typing? I could use it like this:
/// <reference path="lib/jquery.myplugin.d.ts"/>
but that requires me to add a <script>
tag to my HTML, and the library is not loaded asynchronously. I want TypeScript to generate this code:
define(["require", "exports", "lib/jquery.myplugin"], function (require, exports, __jquery.myplugin__) {
...
// Use my plugin
$('#my-element').myExample();
}
However since there are no exports in the .d.ts file I can't write import myplugin = module('lib/jquery.myplugin')
.
The closest I've gotten is to make a jquery.myplugin.d.ts
that references another ts file with the interface declaration and includes at least one export. However there is nothing to export in this library, and in order to get the desired output I have to not only add an export but I have to call it.
Update: I have opened a work item for this on typescript.codeplex.
Share Improve this question edited Nov 6, 2012 at 18:26 dcstraw asked Oct 22, 2012 at 16:42 dcstrawdcstraw 3,3213 gold badges31 silver badges38 bronze badges 1-
My current workaround is to manually call
require([...], () => { ... })
in my TypeScript code, which generates a nested require call. Far from ideal, but it works. – dcstraw Commented Oct 23, 2012 at 18:01
3 Answers
Reset to default 4Kind of a hack but here's the only way I currently know of.
myplugin.d.ts: extends the JQueryStatic interface to include intellisense for myplugin's functionality
/// <reference path="../dep/jquery/jquery.d.ts" />
interface JQueryStatic {
myFunc(): string;
}
myplugin.ts: a dummy file whose only purpose is to have typescript generate an amd module definition.
var test: number = 1;
consumer.ts:
/// <reference path="myplugin.d.ts" />
import myplugin = module('myplugin');
// without this typescript knows you aren't actually using the module
// and won't create the define block including your plugin
var workaround = myplugin.test;
$.myFunc();
consumer.js: generated with tsc -c --module amd consumer.ts
define(["require", "exports", 'myplugin'], function(require, exports, __myplugin__) {
/// <reference path="myplugin.d.ts" />
var myplugin = __myplugin__;
// without this typescript knows you aren't actually using the module
// and won't create the define block including your plugin
var workaround = myplugin.test;
$.myFunc();
})
Note that myplugin.d.ts will pull intellisense in for both jQuery and your plugin definitions. It was necessary to create both a myplugin.d.ts and myplugin.ts because I don't know how (if possible) to export something while simultaneously extending an existing interface in the same file without errors.
Typescript won't import modules unless they export something and unless you directly use what they exported, but those things aren't true for things like JQuery plugins that simply add new methods to $. The solution is to use the amd-dependency flag as documented here.
Add a line like this at the top of your file:
///<amd-dependency path="jgrowl" />
This will force Typescript to list it in the define
invocation in the piled Javascript. You'll also need to set up a path and shim for your plugin in your require.config, like this:
require.config({
paths: {
jquery: "external/jquery-2.1.1",
jgrowl: "external/jquery.jgrowl-1.4.0.min",
},
shim: {
'jgrowl': { deps: ['jquery'] },
}
});
At the bottom of the file that the interface is defined within you can put:
export var JQuery: JQueryStatic;
Which will make the intellisense for JQuery show up on any file loaded using import module
.
If your file is being loaded asynchronously and you're setting JQuery to another variable (i.e. myJQuery) you can declare that the file has already been loaded by a certain point, for example, if you have the file in your ///<reference path=...>
you should be able to use:
declare var myJQuery: JQuery;
To make your myJQuery of type JQuery.
Another hack is to insert the interface directly into the area where the code is being loaded asynchronously:
interface JQueryStatic {
myFunc(): string;
}
If you don't mind editing your JQuery.d.ts files, you can add your function to the interfaces defined in there.
Related back to your example, you should be able to do something like:
declare var __jquery : JQueryStatic;
At the top of your define callback; and provided you've extended the interface for JQueryStatic and included it using ///<reference path=...>
the markup should work as desired.
本文标签: javascriptAsynchronous load of TypeScript declarations with no exportsStack Overflow
版权声明:本文标题:javascript - Asynchronous load of TypeScript declarations with no exports - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742395129a2466768.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论