Comment produire un fichier de définition de «typages» .d.ts à partir d'une bibliothèque JavaScript existante?


199

J'utilise beaucoup de bibliothèques à la fois les miennes et les tierces. Je vois que le répertoire "typings" en contient pour Jquery et WinRT ... mais comment sont-ils créés?

Réponses:


235

Il existe quelques options disponibles pour vous en fonction de la bibliothèque en question, de la manière dont elle est écrite et du niveau de précision que vous recherchez. Passons en revue les options, par ordre décroissant de désirabilité.

Peut-être que ça existe déjà

Vérifiez toujours DefinatelyTyped ( https://github.com/DefinitelyTyped/DefinatelyTyped ) en premier. Il s'agit d'un dépôt communautaire rempli de milliers de fichiers .d.ts et il est très probable que ce que vous utilisez soit déjà là. Vous devriez également vérifier TypeSearch ( https://microsoft.github.io/TypeSearch/ ) qui est un moteur de recherche pour les fichiers .d.ts publiés par NPM; cela aura un peu plus de définitions que DefinatelyTyped. Quelques modules livrent également leurs propres définitions dans le cadre de leur distribution NPM, alors voyez aussi si c'est le cas avant d'essayer d'écrire la vôtre.

Vous n'en avez peut-être pas besoin

TypeScript prend désormais en charge l' --allowJsindicateur et fera plus d'inférences basées sur JS dans les fichiers .js. Vous pouvez essayer d'inclure le fichier .js dans votre compilation avec le --allowJsparamètre pour voir si cela vous donne des informations de type suffisamment bonnes. TypeScript reconnaîtra des éléments tels que les classes de style ES5 et les commentaires JSDoc dans ces fichiers, mais peut être déclenché si la bibliothèque s'initialise d'une manière étrange.

Commencez avec --allowJs

Si --allowJsvous avez obtenu des résultats décents et que vous souhaitez écrire vous-même un meilleur fichier de définition, vous pouvez combiner --allowJsavec --declarationpour voir la "meilleure estimation" de TypeScript sur les types de bibliothèque. Cela vous donnera un bon point de départ, et peut être aussi bon qu'un fichier créé à la main si les commentaires JSDoc sont bien écrits et que le compilateur a pu les trouver.

Premiers pas avec dts-gen

Si --allowJscela ne fonctionne pas, vous pouvez utiliser dts-gen ( https://github.com/Microsoft/dts-gen ) pour obtenir un point de départ. Cet outil utilise la forme d'exécution de l'objet pour énumérer avec précision toutes les propriétés disponibles. Sur le plan positif, cela a tendance à être très précis, mais l'outil ne prend pas encore en charge le grattage des commentaires JSDoc pour remplir des types supplémentaires. Vous exécutez ceci comme ceci:

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

Cela générera your-module.d.tsdans le dossier actuel.

Appuyez sur le bouton Snooze

Si vous voulez simplement tout faire plus tard et vous passer des types pendant un certain temps, dans TypeScript 2.0, vous pouvez maintenant écrire

declare module "foo";

qui vous laissera importle "foo"module avec le type any. Si vous avez un global que vous souhaitez traiter plus tard, écrivez simplement

declare const foo: any;

ce qui vous donnera une foovariable.


25
Aïe ... cela va être un obstacle important à l'entrée dans de nombreux cas. Ce serait bien d'avoir un outil qui pourrait générer au moins les "meilleures estimations" basées sur l'inférence de type. Bien que ceux-ci ne soient pas optimaux, ils pourraient au moins être ajustés au fil du temps.
Hotrodmonkey

7
+1 - Autre bonne nouvelle: --declarationsgénère à la fois le .jsfichier et le .d.tsfichier, ce qui signifie que vous n'avez besoin d'exécuter qu'une seule compilation.
Fenton

67
Une collection de définitions de haute qualité pour les bibliothèques populaires peut être trouvée sur github.com/borisyankov/DefinatelyTyped
Boris Yankov

10
Un outil de «meilleure estimation» ne sera pas meilleur que l'IntelliSense déjà existant dans TypeScript. L'avantage des définitions de type est de fournir plus d'informations au compilateur qu'il ne peut «deviner».
Boris Yankov

12
--allowJsavec les --declarationoptions ne peuvent pas être combinées (testé dans TypeScript 1.8 et 2.0). Si j'essaye, j'obtiens:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey

56

Vous pouvez soit utiliser tsc --declaration fileName.tscomme Ryan décrit, ou vous pouvez spécifier ci- declaration: truedessous compilerOptionsdans votre tsconfig.jsonhypothèse que vous avez déjà eu un tsconfig.jsonsous votre projet.


4
C'est la meilleure réponse si vous développez un ou plusieurs modules Angular 2 que vous souhaitez partager.
Darcy

Si j'essaye, tsc --declaration test.tsj'obtiens l'erreur Cannot find name...pour les types pour lesquels j'essaie de créer un fichier de déclaration :) J'ai donc besoin des types avant de pouvoir les déclarer?
Kokodoko du

2
@Kokodoko, pouvez-vous essayer d'ajouter declaration: trueà votre tsconfig.jsonfichier?
JayKan

Merci, je voulais juste générer * .d.ts à partir de * .ts.
vintproykt

17

La meilleure façon de gérer cela (si un fichier de déclaration n'est pas disponible sur DefinitelyTyped ) est d'écrire des déclarations uniquement pour les éléments que vous utilisez plutôt que pour la bibliothèque entière. Cela réduit beaucoup le travail - et en plus le compilateur est là pour vous aider en se plaignant des méthodes manquantes.


16

Comme le dit Ryan, le compilateur tsc a un commutateur --declarationqui génère un .d.tsfichier à partir d'un .tsfichier. Notez également que (sauf les bogues) TypeScript est censé être capable de compiler Javascript, vous pouvez donc passer du code javascript existant au compilateur tsc.


1
semble actuellement passer des fichiers * .js dans tsc génère une erreur "Erreur de lecture du fichier" angular-resource.js ": Fichier non trouvé". Vous devez donc renommer explicitement les fichiers * .js en * .ts pour pouvoir utiliser tsc. Voir ce numéro pour plus de détails - J'ai essayé de l'utiliser sur angularjs: typescript.codeplex.com/workitem/26
James Strachan

3
d'après ce que je peux dire, tsc peut compiler n'importe quel JavaScript valide, mais s'il n'est pas valide TypeScript (la compilation donne des avertissements) alors l'indicateur --declarations ne produit pas de fichier .d.ts, donc à moins que votre bibliothèque ne soit écrite en TypeScript, vous doivent encore créer manuellement le fichier des déclarations.
agradl


3

Voici un PowerShell qui crée un seul fichier de définition TypeScript, une bibliothèque qui comprend plusieurs *.jsfichiers avec JavaScript moderne.

Tout d'abord, changez toutes les extensions en .ts.

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

Deuxièmement, utilisez le compilateur TypeScript pour générer des fichiers de définition. Il y aura un tas d'erreurs du compilateur, mais nous pouvons les ignorer.

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

Enfin, combinez tous les *.d.tsfichiers en un seul index.d.ts, en supprimant les importinstructions et en supprimant le defaultde chaque instruction d'exportation.

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

Cela se termine par un seul index.d.tsfichier utilisable qui comprend de nombreuses définitions.


2
Deuxième étape, Get-ChildItem | foreach {tsc --declaration $ _. Name} a fonctionné (ajout du paramètre --declaration manquant)
Guru_07

3

Lors de la création de votre propre bibliothèque, vous pouvez créer des *.d.tsfichiers en utilisant la commande tsc(TypeScript Compiler) comme ceci: (en supposant que vous construisez votre bibliothèque dans le dist/libdossier)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): génère les *.d.tsfichiers
  • --declarationDir dist/lib: Répertoire de sortie des fichiers de déclaration générés.
  • --declarationMap: Génère un sourcemap pour chaque fichier '.d.ts' correspondant.
  • --emitDeclarationOnly: Émettre uniquement les fichiers de déclaration '.d.ts'. (pas de JS compilé)

(voir la documentation pour toutes les options du compilateur en ligne de commande)

Ou par exemple dans votre package.json:

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

puis exécutez: yarn build:types(ou npm run build:types)


Je n'arrive toujours pas à comprendre comment générer les d.tsfichiers et utiliser les interfaces. Avez-vous des exemples?
Danosaure le

Le script npm ci-dessus générera les *.d.tsfichiers et les placera dans le dist/libdossier. Vous avez besoin d'un tsconfig.jsonfichier à la racine de votre projet, mais il doit être là pour que le projet fonctionne quand même.
magikMaker le

Je suis incapable de les utiliser, une fois exposés. J'ai le post stackoverflow.com/questions/59742688 si vous pouvez le faire fonctionner?
Danosaure le

2

Je rechercherais un mappage existant de vos bibliothèques JS tierces qui prennent en charge Script # ou SharpKit. Les utilisateurs de ces compilateurs croisés C # vers .js auront été confrontés au problème auquel vous êtes maintenant confronté et auront peut-être publié un programme open source pour analyser votre bibliothèque tierce et la convertir en classes C # squelettes. Si c'est le cas, piratez le programme du scanner pour générer TypeScript à la place de C #.

À défaut, la traduction d'une interface publique C # pour votre bibliothèque tierce en définitions TypeScript pourrait être plus simple que de faire de même en lisant le JavaScript source.

Mon intérêt particulier est le framework ExtJS RIA de Sencha et je sais qu'il y a eu des projets publiés pour générer une interprétation C # pour Script # ou SharpKit


FYI: Je viens de faire mon premier fichier de définition dactylographié pour Sencha / ExtJS: github.com/andremussche/extjsTypescript/blob/master/jsondocs/…
André

hé Camel Case, j'ai mis en place un blog sur l'utilisation des ExtJ avec dactylographié: blorkfish.wordpress.com/2013/01/28/using-extjs-with-typescript
blorkfish
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.