2012-10-22 28 views
6

Mam wiele wtyczek jQuery, które chciałbym wczytać przy użyciu wzorca AMD w TypeScript. Na przykład, mogę mieć tę strukturę:Asynchroniczne ładowanie deklaracji TypeScript bez eksportu

/lib/jquery.myplugin.js 
/app.ts 

Wtyczka rozszerza jQuery. Nie zapewnia nowych funkcji lub zmiennych najwyższego poziomu. Przykładem może być:

// jquery.myplugin.js 
jQuery.fn.myExample = function() { ... } 

odpowiedni plik jquery.myplugin.d.ts wygląda następująco:

interface JQuery { 
    myExample(); 
} 

tak, że teraz w app.ts mogę nazwać coś takiego $('#my-element').myExample(). Zauważ, że to zakłada, że ​​mam już załadowane deklaracje jquery.d.ts z Microsoft.

Moje pytanie brzmi: jak ładować tę bibliotekę asynchronicznie i korzystać ze statycznego pisania typu? można go używać tak:

/// <reference path="lib/jquery.myplugin.d.ts"/> 

ale to wymaga ode mnie dodać do mojego <script> tag HTML, a biblioteka nie jest ładowany asynchronicznie. Chcę maszynopis do wygenerowania tego kodu:

define(["require", "exports", "lib/jquery.myplugin"], function (require, exports, __jquery.myplugin__) { 
    ... 
    // Use my plugin 
    $('#my-element').myExample(); 
} 

Jednak ponieważ nie ma eksportu w .d.ts plik nie mogę napisać import myplugin = module('lib/jquery.myplugin').

Najbliższym, co udało mi się zrobić, jest utworzenie jquery.myplugin.d.ts, który odwołuje się do innego pliku ts z deklaracją interfejsu i zawiera co najmniej jeden eksport. Jednak w tej bibliotece nie ma niczego do wyeksportowania, a żeby uzyskać pożądany wynik, muszę nie tylko dodać eksport, ale muszę go nazwać.

Aktualizacja: Mam otworzył work item za to na typescript.codeplex.com

+0

Moje bieżące obejście jest ręcznie wywołać 'wymagają ([...],() => {...}) 'w moim kodzie TypeScript, który generuje zagnieżdżone wywołanie wymagające. Daleko od ideału, ale działa. – dcstraw

Odpowiedz

3

Maszynka do pisania nie będzie importować modułów, chyba że wyeksportuje coś i jeśli nie użyjesz bezpośrednio tego, co wyeksportował, ale te rzeczy nie są prawdziwe dla rzeczy takich jak wtyczki JQuery, które po prostu dodają nowe metody do $. Rozwiązaniem jest użycie flagi zależności amd zgodnie z dokumentacją here.

Dodaj linię jak to u góry pliku:

///<amd-dependency path="jgrowl" /> 

To zmusi go do listy maszynopis w define inwokacji w skompilowanej JavaScript. Trzeba także ustawić ścieżkę i podkładkę dla swojej wtyczki w require.config, tak:

require.config({ 
    paths: { 
    jquery: "external/jquery-2.1.1", 
    jgrowl: "external/jquery.jgrowl-1.4.0.min", 
    }, 
    shim: { 
    'jgrowl': { deps: ['jquery'] }, 
    } 
}); 
+0

Doskonale, bardzo dziękuję. Nie sądzę, że ta funkcja istniała, gdy zadałem pytanie. Wygląda dokładnie tak, jak tego szukałem. – dcstraw

4

rodzaj hack, ale tutaj jest jedynym sposobem Obecnie wiadomo.

myplugin.d.ts: rozszerza JQueryStatic interfejs obejmują intellisense dla funkcjonalności myplugin za

/// <reference path="../dep/jquery/jquery.d.ts" /> 

interface JQueryStatic { 
    myFunc(): string; 
} 

myplugin.ts: plik manekina, którego jedynym celem jest, aby mieć maszynopis wygenerowania amd definicję modułu .

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: generowane z 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(); 
}) 

Zauważ, że myplugin.d.ts będzie ciągnąć w intellisense dla zarówno jQuery, jak i definicje wtyczek. Konieczne było utworzenie zarówno myplugin.d.ts, jak i myplugin.ts, ponieważ nie wiem jak (jeśli to możliwe) wyeksportować coś przy jednoczesnym rozszerzeniu istniejącego interfejsu w tym samym pliku bez błędów.

+0

Wygląda na to, że musiałbyś zdefiniować ścieżkę w configie requirejs (lub jakimkolwiek innym programie ładującym AMD), która kojarzy 'myplugin' ze ścieżką do wtyczki, prawda? W przeciwnym razie, jeśli umieścisz plik myplugin.d.ts w tej samej lokalizacji co wtyczka, skompilowany plik js zastąpi bibliotekę wtyczek. – dcstraw

+0

Tylko jeśli kompilator został uruchomiony z flagą definicji i nie określił alternatywnego katalogu wyjściowego. Po prostu wyświetli domyślnie plik myplugin.js. – ryan

+0

Mówię, że myplugin.js to prawdopodobnie nazwa twojej biblioteki w tym przypadku. W moim przykładzie zaimportowałem "lib/jquery.myplugin". Więc bez aliasingu nazwy zależności wygenerowany plik JavaScript nadpisze twoją bibliotekę. – dcstraw

1

Na dole pliku, że interfejs został zdefiniowany w was może umieścić:

export var JQuery: JQueryStatic; 

co uczyni intellisense dla jQuery pokazać się na dowolny plik załadowany, używając import module.

Jeśli plik jest ładowany asynchronicznie i jesteś ustawienie JQuery do innej zmiennej (tj myJQuery) można zadeklarować, że plik został już załadowany przez pewnym momencie, na przykład, jeśli masz plik w ///<reference path=...> powinieneś być w stanie używać:

declare var myJQuery: JQuery; 

aby dokonać myJQuery typu JQuery.

Kolejny Hack jest dodanie interfejsu bezpośrednio do obszaru, gdzie kod jest ładowany asynchronicznie:

interface JQueryStatic { 
    myFunc(): string; 
} 

Jeśli nie przeszkadza edycji JQuery.d.ts plików, możesz dodać swoją funkcję do zdefiniowanych tam interfejsów.

powiązane z powrotem do przykładu, powinieneś być w stanie zrobić coś takiego:

declare var __jquery : JQueryStatic; 

Na górze zdefiniowania zwrotnego; i pod warunkiem, że interfejs został rozszerzony o JQueryStatic i uwzględnił go przy użyciu ///<reference path=...> znacznik powinien działać zgodnie z oczekiwaniami.

+0

Sam nie używałem AMD, ale mam nadzieję, że to pomoże! – Griffork

+0

Deklarowanie zmiennych globalnych działa dobrze dla bibliotek ładowanych za pomocą innych środków, np. znacznik skryptu w kodzie HTML. Zaletą modelu AMD jest to, że pozwala zadeklarować swoją zależność i załadować ją w razie potrzeby lub dołączyć do pakietu w czasie kompilacji, a globalna przestrzeń nazw nie musi być zanieczyszczona. To jest właśnie to, co nie jest dobrze obsługiwane w TypeScript dla bibliotek, które nie mają eksportów najwyższego poziomu. – dcstraw

+0

Przepraszam, myślałem, że wzór AMD zadziałał w stylu wywołania zwrotnego? Jeśli tak, to czy nie byłoby możliwe zadeklarowanie zmiennej z interfejsem JQuery w wywołaniu zwrotnym? Następnie wyświetliłoby się tylko dla intellisense w callback, a nie w reszcie pliku. – Griffork

Powiązane problemy