Асинхронная загрузка объявлений TypeScript без экспорта
у меня есть несколько плагинов jQuery, которые я хотел бы загрузить с помощью шаблона AMD в TypeScript. Например, у меня может быть такая структура:
/lib/jquery.myplugin.js
/app.ts
плагин просто расширяет jQuery. Это не дает никаких новых функций или переменных. Примером может служить:
// jquery.myplugin.js
jQuery.fn.myExample = function() { ... }
соответствующий jquery.myplugin.д.TS файл выглядит так:
interface JQuery {
myExample();
}
так что теперь в приложение.ТС я могу назвать что-то вроде $('#my-element').myExample()
. Обратите внимание, что это предполагает, что у меня уже есть на jQuery.d.загружены объявления ts от Microsoft.
мой вопрос: как мне загрузить эту библиотеку асинхронно и воспользоваться рукописи статическая типизация? Я мог бы использовать его так:
/// <reference path="lib/jquery.myplugin.d.ts"/>
но это требует от меня, чтобы добавить <script>
тег в HTML, и библиотека не загружается асинхронно. Я хочу, чтобы TypeScript генерировал этот код:
define(["require", "exports", "lib/jquery.myplugin"], function (require, exports, __jquery.myplugin__) {
...
// Use my plugin
$('#my-element').myExample();
}
однако, поскольку в нем нет экспорта .d.TS файл я не могу написать import myplugin = module('lib/jquery.myplugin')
.
в самое близкое, что я получил, - это сделать jquery.myplugin.d.ts
, который ссылается на другой файл TS с объявлением интерфейса и включает по крайней мере один экспорт. Однако в этой библиотеке нечего экспортировать, и чтобы получить желаемый результат, я должен не только добавить экспорт, но и вызвать его.
обновление: я открыл элемент на typescript.codeplex.com
3 ответов
Typescript не будет импортировать модули, если они не экспортируют что-то и если вы напрямую не используете то, что они экспортировали, но это не верно для таких вещей, как плагины JQuery, которые просто добавляют новые методы в $. Решение заключается в использовании драм-зависимость флаг, как описано здесь.
добавить такую строку в верхней части файла:
///<amd-dependency path="jgrowl" />
это заставит Typescript перечислить его в define
вызов в скомпилированном Javascript. Вам также понадобится чтобы настроить путь и прокладку для вашего плагина в вашем require.config, например:
require.config({
paths: {
jquery: "external/jquery-2.1.1",
jgrowl: "external/jquery.jgrowl-1.4.0.min",
},
shim: {
'jgrowl': { deps: ['jquery'] },
}
});
вид взлома, но вот единственный способ, который я в настоящее время знаю.
myplugin.д.ТС: расширяет интерфейс JQueryStatic, чтобы включить intellisense для функциональности myplugin
/// <reference path="../dep/jquery/jquery.d.ts" />
interface JQueryStatic {
myFunc(): string;
}
myplugin.ТС: фиктивный файл, единственной целью которого является создание typescript определения модуля amd.
var test: number = 1;
потребитель.ТС:
/// <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();
потребитель.js: созданный с 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();
})
отметим, что myplugin.д.ТС вытащит intellisense как для jQuery, так и для ваших определений плагинов. Необходимо было создать оба myplugin.d.ts и myplugin.ts, потому что я не знаю, как (если возможно) экспортировать что-то, одновременно расширяя существующий интерфейс в том же файле без ошибок.
в нижней части файла, что интерфейс определен внутри вы можете поместить:
export var JQuery: JQueryStatic;
что сделает intellisense для JQuery отображаться в любом файле, загруженном с помощью import module
.
если ваш файл загружается асинхронно, а вы в jQuery другой переменной (т. е. myJQuery) вы можете объявить, что файл уже загружен определенной точкой, например, если у вас есть файл в вашем ///<reference path=...>
вы должны быть возможность использования:
declare var myJQuery: JQuery;
чтобы сделать ваш myJQuery типа в jQuery.
другой Хак-вставить интерфейс непосредственно в область, где код загружается асинхронно:
interface JQueryStatic {
myFunc(): string;
}
если вы не против редактирования JQuery.d.TS-файлы, вы можете добавить свою функцию к интерфейсам, определенным там.
связанный с вашим примером, вы должны быть в состоянии сделать что-то вроде:
declare var __jquery : JQueryStatic;
At верхняя часть вашего обратного вызова define; и при условии, что вы расширили интерфейс для JQueryStatic и включил его с помощью ///<reference path=...>
разметка должна работать по желанию.