Wie erstellen Sie eine .d.ts-Definitionsdatei für Typisierungen aus einer vorhandenen JavaScript-Bibliothek?

192

Ich verwende viele Bibliotheken, sowohl meine eigenen als auch die von Drittanbietern. Ich sehe, dass das Verzeichnis "typings" einige für Jquery und WinRT enthält ... aber wie werden sie erstellt?

Hotrodmonkey
quelle

Antworten:

232

Abhängig von der jeweiligen Bibliothek, der Schreibweise und der gewünschten Genauigkeit stehen Ihnen einige Optionen zur Verfügung. Lassen Sie uns die Optionen in ungefähr absteigender Reihenfolge der Erwünschtheit überprüfen.

Vielleicht existiert es bereits

Überprüfen Sie immer zuerst DefinitelyTyped ( https://github.com/DefinitelyTyped/DefinitelyTyped ). Dies ist ein Community-Repo mit buchstäblich Tausenden von .d.ts-Dateien, und es ist sehr wahrscheinlich, dass das, was Sie verwenden, bereits vorhanden ist. Sie sollten auch TypeSearch ( https://microsoft.github.io/TypeSearch/ ) überprüfen, eine Suchmaschine für NPM-veröffentlichte .d.ts-Dateien. Dies hat etwas mehr Definitionen als DefinitelyTyped. Einige Module liefern im Rahmen ihrer NPM-Verteilung auch ihre eigenen Definitionen aus. Überprüfen Sie daher, ob dies der Fall ist, bevor Sie versuchen, Ihre eigenen zu schreiben.

Vielleicht brauchst du keinen

TypeScript unterstützt jetzt das --allowJsFlag und führt weitere JS-basierte Schlussfolgerungen in .js-Dateien durch. Sie können versuchen, die .js-Datei zusammen mit der --allowJsEinstellung in Ihre Kompilierung aufzunehmen, um festzustellen , ob Sie dadurch ausreichend Typinformationen erhalten . TypeScript erkennt Dinge wie ES5-Klassen und JSDoc-Kommentare in diesen Dateien, kann jedoch ausgelöst werden, wenn sich die Bibliothek auf seltsame Weise selbst initialisiert.

Erste Schritte mit --allowJs

Wenn --allowJsgab dir anständige Ergebnisse und Sie wollen eine bessere Definition Datei schreiben selbst, Sie kombinieren --allowJsmit --declarationTyposkript der „best guess“ auf die Arten der Bibliothek zu sehen. Dies gibt Ihnen einen anständigen Ausgangspunkt und ist möglicherweise so gut wie eine von Hand erstellte Datei, wenn die JSDoc-Kommentare gut geschrieben sind und der Compiler sie finden konnte.

Erste Schritte mit dts-gen

Wenn --allowJsdies nicht funktioniert hat, können Sie dts-gen ( https://github.com/Microsoft/dts-gen ) verwenden, um einen Ausgangspunkt zu erhalten. Dieses Tool verwendet die Laufzeitform des Objekts, um alle verfügbaren Eigenschaften genau aufzulisten. Auf der positiven Seite ist dies in der Regel sehr genau, aber das Tool unterstützt das Scrapen der JSDoc-Kommentare zum Auffüllen zusätzlicher Typen noch nicht. Du machst das so:

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

Dies wird your-module.d.tsim aktuellen Ordner generiert .

Drücke die Schlummertaste

Wenn Sie alles nur später erledigen und eine Weile ohne Typen auskommen möchten, können Sie jetzt in TypeScript 2.0 schreiben

declare module "foo";

Damit können Sie importdas "foo"Modul mit Typ any. Wenn Sie eine globale haben, mit der Sie sich später befassen möchten, schreiben Sie einfach

declare const foo: any;

das gibt Ihnen eine fooVariable.

Ryan Cavanaugh
quelle
25
Autsch ... das wird in vielen Fällen eine bedeutende Eintrittsbarriere sein. Es wäre schön, ein Tool zu haben, das zumindest "beste Vermutungen" basierend auf Typinferenz ausgeben könnte. Obwohl diese möglicherweise nicht optimal sind, können sie zumindest im Laufe der Zeit angepasst werden.
Hotrodmonkey
7
+1 - Weitere gute Nachrichten: --declarationsGeneriert sowohl die .jsDatei als auch die .d.tsDatei, sodass Sie nur eine einzige Kompilierung ausführen müssen.
Fenton
67
Eine Sammlung hochwertiger Definitionen für beliebte Bibliotheken finden Sie unter github.com/borisyankov/DefinitelyTyped
Boris Yankov
10
Ein Best-Guess-Tool ist nicht besser als das bereits in TypeScript vorhandene IntelliSense. Der Vorteil der Typdefinitionen besteht darin, dass dem Compiler mehr Informationen zur Verfügung gestellt werden, als er erraten kann.
Boris Yankov
12
--allowJsmit --declarationOptionen können nicht kombiniert werden (getestet in TypeScript 1.8 und 2.0). Wenn ich es versuche, bekomme ich:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey
52

Sie können entweder tsc --declaration fileName.tswie Ryan beschreibt, oder Sie können festlegen , declaration: trueunter compilerOptionsin Ihrer tsconfig.jsonvorausgesetzt , Sie haben bereits eine haben tsconfig.jsonunter Ihrem Projekt.

JayKan
quelle
4
Dies ist die beste Antwort, wenn Sie ein Angular 2-Modul entwickeln, das Sie freigeben möchten.
Darcy
Wenn ich es versuche, tsc --declaration test.tserhalte ich den Fehler Cannot find name...für die Typen, für die ich eine Deklarationsdatei erstellen möchte :) Also brauche ich die Typen, bevor ich sie deklarieren kann?
Kokodoko
2
@ Kokodoko, können Sie versuchen declaration: true, Ihrer tsconfig.jsonDatei hinzuzufügen ?
JayKan
Danke, ich wollte nur * .d.ts aus * .ts generieren.
vintproykt
16

Der beste Weg, um damit umzugehen (wenn eine Deklarationsdatei auf DefinitelyTyped nicht verfügbar ist ), besteht darin, Deklarationen nur für die von Ihnen verwendeten Dinge und nicht für die gesamte Bibliothek zu schreiben. Dies reduziert die Arbeit erheblich - und der Compiler hilft zusätzlich, indem er sich über fehlende Methoden beschwert.

Gorgi Kosev
quelle
15

Wie Ryan sagt, hat der tsc-Compiler einen Schalter, --declarationder eine .d.tsDatei aus einer .tsDatei generiert . Beachten Sie auch, dass TypeScript (mit Ausnahme von Fehlern) Javascript kompilieren kann, damit Sie vorhandenen Javascript-Code an den tsc-Compiler übergeben können.

CCoder
quelle
1
scheint derzeit * .js-Dateien an tsc zu übergeben, erzeugt einen Fehler "Fehler beim Lesen der Datei" angle-resource.js ": Datei nicht gefunden". Sie müssen also * .js-Dateien explizit in * .ts umbenennen, um tsc verwenden zu können. Sehen Sie diese Frage für weitere Details - Ich habe versucht , mit diesem auf AngularJS: typescript.codeplex.com/workitem/26
James Strachan
3
Nach allem, was ich sagen kann, kann tsc jedes gültige JavaScript kompilieren. Wenn es jedoch kein gültiges TypeScript ist (Kompilieren gibt Warnungen aus), gibt das Flag --declarations keine .d.ts-Datei aus, es sei denn, Ihre Bibliothek ist in TypeScript you geschrieben Die Deklarationsdatei muss noch manuell erstellt werden.
Agradl
3

Hier ist eine PowerShell, die eine einzelne TypeScript-Definitionsdatei erstellt, eine Bibliothek, die mehrere *.jsDateien mit modernem JavaScript enthält.

Ändern Sie zunächst alle Erweiterungen in .ts.

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

Verwenden Sie zweitens den TypeScript-Compiler, um Definitionsdateien zu generieren. Es wird eine Reihe von Compilerfehlern geben, die wir jedoch ignorieren können.

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

Kombinieren Sie schließlich alle *.d.tsDateien zu einer index.d.ts, entfernen Sie die importAnweisungen und entfernen Sie die defaultaus jeder Exportanweisung.

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 $_ }

Dies endet mit einer einzelnen verwendbaren index.d.tsDatei, die viele der Definitionen enthält.

Shaun Luttin
quelle
2
Zweiter Schritt, Get-ChildItem | foreach {tsc --declaration $ _. Name} hat funktioniert (fehlender --declaration param hinzugefügt)
Guru_07
3

Wenn Sie Ihre eigene Bibliothek erstellen, können Sie *.d.tsDateien mit dem tscBefehl (TypeScript Compiler) wie folgt erstellen : (vorausgesetzt , Sie erstellen Ihre Bibliothek im dist/libOrdner)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): generiert die *.d.tsDateien
  • --declarationDir dist/lib: Ausgabeverzeichnis für generierte Deklarationsdateien.
  • --declarationMap: Erzeugt eine Quellenkarte für jede entsprechende '.d.ts'-Datei.
  • --emitDeclarationOnly: Nur '.d.ts'-Deklarationsdateien ausgeben. (kein kompiliertes JS)

( Alle Befehlszeilen-Compileroptionen finden Sie in den Dokumenten. )

Oder zum Beispiel in Ihrem package.json:

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

und dann ausführen: yarn build:types(oder npm run build:types)

magikMaker
quelle
Ich kann immer noch nicht herausfinden, wie ich die d.tsDateien generieren und Schnittstellen verwenden kann. Hast du irgendwelche Beispiele?
Danosaure
Das obige npm-Skript generiert die *.d.tsDateien und legt sie im dist/libOrdner ab. Sie benötigen zwar eine tsconfig.jsonDatei im Stammverzeichnis Ihres Projekts, diese sollte jedoch vorhanden sein, damit das Projekt trotzdem funktioniert.
magikMaker
Ich kann sie nicht verwenden, wenn sie einmal freigelegt sind. Ich habe den folgenden Beitrag stackoverflow.com/questions/59742688, wenn Sie es zum Laufen bringen können?
Danosaure
2

Ich würde nach einer vorhandenen Zuordnung Ihrer JS-Bibliotheken von Drittanbietern suchen, die Script # oder SharpKit unterstützen. Benutzer dieser Cross-Compiler von C # zu .js haben das Problem, mit dem Sie jetzt konfrontiert sind, und haben möglicherweise ein Open-Source-Programm veröffentlicht, mit dem Sie Ihre Drittanbieter-Bibliothek scannen und in Skelett-C # -Klassen konvertieren können. Wenn ja, hacken Sie das Scannerprogramm, um TypeScript anstelle von C # zu generieren.

Andernfalls ist das Übersetzen einer öffentlichen C # -Schnittstelle für Ihre Drittanbieter-Bibliothek in TypeScript-Definitionen möglicherweise einfacher als das Lesen des Quell-JavaScript.

Mein besonderes Interesse gilt Senchas ExtJS RIA-Framework, und ich weiß, dass Projekte veröffentlicht wurden, um eine C # -Interpretation für Script # oder SharpKit zu generieren

camelCase
quelle
Zu Ihrer Information: Ich habe gerade meine erste Typoskript-Definitionsdatei für Sencha / ExtJS erstellt: github.com/andremussche/extjsTypescript/blob/master/jsondocs/…
André
Hey Camel Case, ich habe einen Blog über die Verwendung von ExtJs mit Typoskript zusammengestellt: blorkfish.wordpress.com/2013/01/28/using-extjs-with-typescript
blorkfish