Асинхронная загрузка объявлений 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=...> разметка должна работать по желанию.