Jak utworzyć plik definicji „typowania” .d.ts z istniejącej biblioteki JavaScript?

192

Korzystam z wielu bibliotek, zarówno własnych, jak i zewnętrznych. Widzę, że katalog „typings” zawiera trochę Jquery i WinRT ... ale jak są tworzone?

Hotrodmonkey
źródło

Odpowiedzi:

232

Dostępnych jest kilka opcji, w zależności od biblioteki, o której mowa, w jaki sposób jest napisana i jakiego poziomu dokładności szukasz. Przyjrzyjmy się opcjom w przybliżeniu malejącym porządku pożądania.

Może już istnieje

Zawsze najpierw sprawdź ZdecydowanieTyped ( https://github.com/DefinitelyTyped/DefinitelyTyped ). Jest to repozytorium społeczności pełne dosłownie tysięcy plików .d.ts i jest bardzo prawdopodobne, że używasz już tego. Powinieneś także sprawdzić TypeSearch ( https://microsoft.github.io/TypeSearch/ ), która jest wyszukiwarką plików .d.ts opublikowanych przez NPM; to będzie miało nieco więcej definicji niż DefinentlyTyped. Kilka modułów dostarcza również własne definicje w ramach dystrybucji NPM, więc sprawdź, czy tak jest przed próbą napisania własnych.

Może nie potrzebujesz

TypeScript obsługuje teraz --allowJsflagę i uczyni więcej wniosków opartych na JS w plikach .js. Możesz spróbować dołączyć plik .js do kompilacji wraz z --allowJsustawieniem, aby sprawdzić, czy daje to wystarczająco dobre informacje o typie. TypeScript rozpozna w tych plikach klasy typu ES5 i komentarze JSDoc, ale może się potknąć, jeśli biblioteka zainicjuje się w dziwny sposób.

Rozpocznij z --allowJs

Jeśli --allowJsdałeś przyzwoite wyniki i chcesz sam napisać plik lepszej definicji, możesz połączyć go --allowJsz, --declarationaby zobaczyć „najlepsze odgadnięcie” TypeScript na temat typów bibliotek. To da ci dobry punkt wyjścia i może być tak dobry, jak ręcznie napisany plik, jeśli komentarze JSDoc są dobrze napisane, a kompilator był w stanie je znaleźć.

Rozpocznij z dts-gen

Jeśli --allowJsnie zadziałało, możesz użyć dts-gen ( https://github.com/Microsoft/dts-gen ), aby uzyskać punkt początkowy. To narzędzie używa kształtu środowiska wykonawczego obiektu do dokładnego wyliczenia wszystkich dostępnych właściwości. Na plus jest to zwykle bardzo dokładne, ale narzędzie nie obsługuje jeszcze skrobania komentarzy JSDoc w celu wypełnienia dodatkowych typów. Uruchamiasz to tak:

npm install -g dts-gen
dts-gen -m <your-module>

To wygeneruje your-module.d.tsw bieżącym folderze.

Naciśnij przycisk drzemki

Jeśli chcesz zrobić to wszystko później i przez jakiś czas nie używać typów, w TypeScript 2.0 możesz teraz pisać

declare module "foo";

co pozwoli ci importna "foo"moduł z typem any. Jeśli masz globalny dokument, z którym chcesz poradzić sobie później, po prostu napisz

declare const foo: any;

co da ci foozmienną.

Ryan Cavanaugh
źródło
25
Ojej ... w wielu przypadkach będzie to znacząca bariera wejścia. Byłoby miło mieć narzędzie, które mogłoby generować co najmniej „najlepsze domysły” na podstawie wnioskowania o typie. Chociaż mogą nie być optymalne, można je przynajmniej z czasem dostroić.
Hotrodmonkey
7
+1 - Dalsze dobre wiadomości: --declarationsgeneruje zarówno .jsplik, jak i .d.tsplik, co oznacza, że ​​wystarczy uruchomić tylko jedną kompilację.
Fenton,
67
Zbiór wysokiej jakości definicji popularnych bibliotek można znaleźć na stronie github.com/borisyankov/DefinitelyTyped
Boris Yankov,
10
Narzędzie „najlepszego odgadnięcia” nie będzie lepsze niż IntelliSense już istniejące w TypeScript. Zaletą definicji typów jest dostarczenie kompilatorowi większej ilości informacji, niż może „odgadnąć”.
Boris Yankov,
12
--allowJsz --declarationopcjami nie można łączyć (testowane w TypeScript 1.8 i 2.0). Jeśli spróbuję, otrzymam:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey
52

Można użyć tsc --declaration fileName.tsjak Ryan opisuje, czy można określić declaration: truena podstawie compilerOptionsw swojej tsconfig.jsonzakładając już miał tsconfig.jsonpod swoim projektem.

JayKan
źródło
4
To najlepsza odpowiedź, jeśli opracowujesz moduły Angular 2, które chcesz udostępnić.
Darcy,
Jeśli spróbuję, pojawia tsc --declaration test.tssię błąd Cannot find name...dla typów, dla których próbuję utworzyć plik deklaracji :) Więc potrzebuję typów, zanim będę mógł je zadeklarować?
Kokodoko
2
@Kokodoko, czy możesz spróbować dodać declaration: truedo swojego tsconfig.jsonpliku?
JayKan
Dzięki, właśnie chciałem wygenerować * .d.ts z * .ts.
vintproykt
16

Najlepszym sposobem na poradzenie sobie z tym (jeśli plik deklaracji nie jest dostępny w ZdecydowanieTyped ) jest pisanie deklaracji tylko dla rzeczy, których używasz, a nie dla całej biblioteki. To znacznie zmniejsza nakład pracy - a dodatkowo kompilator jest w stanie pomóc, narzekając na brakujące metody.

Gorgi Kosev
źródło
15

Jak mówi Ryan, kompilator tsc ma przełącznik, --declarationktóry generuje .d.tsplik z .tspliku. Zauważ też, że (z wyjątkiem błędów) TypeScript powinien być w stanie kompilować Javascript, więc możesz przekazać istniejący kod javascript do kompilatora tsc.

CCoder
źródło
1
wydaje się, że obecnie przekazuje pliki * .js do tsc generuje błąd „Błąd odczytu pliku” angular-resource.js ”: Nie znaleziono pliku”. Musisz więc jawnie zmienić nazwę plików * .js na * .ts, aby móc korzystać z tsc. Zobacz ten problem po więcej szczegółów - Próbowałem za to na angularjs: typescript.codeplex.com/workitem/26
James Strachan
3
z tego co mogę powiedzieć, tsc może skompilować dowolny poprawny JavaScript, ale jeśli nie jest poprawny TypeScript (kompilacja daje ostrzeżenia), to flaga --declarations nie wyświetla pliku .d.ts, więc jeśli twoja biblioteka nie jest napisana w TypeScript nadal trzeba ręcznie utworzyć plik deklaracji.
agradl
3

Oto niektóre PowerShell, który tworzy pojedynczy plik definicji TypeScript, bibliotekę zawierającą wiele *.jsplików z nowoczesnym JavaScript.

Najpierw zmień wszystkie rozszerzenia na .ts.

Get-ChildItem | foreach { Rename-Item $_ $_.Name.Replace(".js", ".ts") }

Po drugie, użyj kompilatora TypeScript do wygenerowania plików definicji. Będzie wiele błędów kompilatora, ale możemy je zignorować.

Get-ChildItem | foreach { tsc $_.Name  }

Na koniec połącz wszystkie *.d.tspliki w jeden index.d.ts, usuwając importinstrukcje i usuwając je defaultz każdej instrukcji eksportu.

Remove-Item index.d.ts; 

Get-ChildItem -Path *.d.ts -Exclude "Index.d.ts" | `
  foreach { Get-Content $_ } | `
  where { !$_.ToString().StartsWith("import") } | `
  foreach { $_.Replace("export default", "export") } | `
  foreach { Add-Content index.d.ts $_ }

Kończy się to jednym użytecznym index.d.tsplikiem, który zawiera wiele definicji.

Shaun Luttin
źródło
2
Drugi krok, Get-ChildItem | foreach {tsc --declaration $ _. Name} zadziałał (dodano brak - parametr deklaracji)
Guru_07
3

Tworząc własną bibliotekę, możesz tworzyć *.d.tspliki za pomocą tsckomendy (TypeScript Compiler) w następujący sposób: (zakładając, że budujesz bibliotekę do dist/libfolderu)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): generuje *.d.tspliki
  • --declarationDir dist/lib: Katalog wyjściowy dla wygenerowanych plików deklaracji.
  • --declarationMap: Generuje sourcemap dla każdego odpowiedniego pliku „.d.ts”.
  • --emitDeclarationOnly: Emituj tylko pliki deklaracji „.d.ts”. (brak skompilowanego JS)

(zobacz dokumentację wszystkich opcji kompilatora wiersza poleceń)

Lub na przykład w package.json:

"scripts": {
    "build:types": "tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly",
}

a następnie uruchom: yarn build:types(lub npm run build:types)

magikMaker
źródło
Nadal nie wiem, jak wygenerować d.tspliki i móc korzystać z interfejsów. Czy masz jakieś przykłady?
Danosaure
Powyższy skrypt npm wygeneruje *.d.tspliki i umieści je w dist/libfolderze. Potrzebny jest tsconfig.jsonplik w katalogu głównym projektu, ale i tak powinien on istnieć, aby projekt mógł działać.
magikMaker
Po ich ujawnieniu nie jestem w stanie ich użyć. Mam następujący post stackoverflow.com/questions/59742688, jeśli możesz to zrobić?
Danosaure
2

Poszukałbym istniejącego mapowania bibliotek JS innych firm, które obsługują Script # lub SharpKit. Użytkownicy tych kompilatorów krzyżowych C # do .js napotkają problem, z którym się teraz borykają, i mogą opublikować program open source do skanowania bibliotek innych firm i konwersji do szkieletowych klas C #. Jeśli tak, zhakuj program skanujący, aby wygenerować TypeScript zamiast C #.

W przeciwnym razie tłumaczenie publicznego interfejsu C # dla biblioteki innych firm na definicje TypeScript może być prostsze niż robienie tego samego przez odczytanie źródłowego JavaScript.

Moim szczególnym zainteresowaniem jest framework ExtJS RIA firmy Sencha i wiem, że opublikowano projekty generujące interpretację C # dla Script # lub SharpKit

camelCase
źródło
FYI: Właśnie stworzyłem swój pierwszy plik definicji maszynopisu dla Sencha / ExtJS: github.com/andremussche/extjsTypescript/blob/master/jsondocs/…
André
hej, Camel Case, założyłem bloga na temat używania ExtJs z maszynopisem: blorkfish.wordpress.com/2013/01/28/using-extjs-with-typescript
blorkfish