Comment puis-je voir comment TypeScript calcule les types?

18

Problème: je travaille sur un fichier qui contient de nombreux types conditionnels qui dérivent leurs types à partir de types conditionnels précédemment définis, ce qui est devenu très complexe et difficile à déboguer sur la façon dont un type est dérivé.

J'essaie de trouver un moyen de "déboguer" ou de lister comment le compilateur TypeScript effectue sa détermination sur un type conditionnel et choisit un chemin pour dériver le type ultime.

J'ai parcouru les options du compilateur et je n'ai encore rien trouvé dans ce domaine ...

Une analogie avec ce que je recherche en ce moment est l'équivalent du DEBUG=express:*type de paramètre que l'on pourrait utiliser si vous vouliez voir ce que faisait un serveur express.

Cependant, le problème réel que j'essaie de résoudre est de pouvoir déconstruire et déboguer comment un type est dérivé dans une grande définition de type hiérarchique complexe.

Remarque importante: je n'essaie pas de déboguer l'exécution au moment de l'exécution du projet TypeScript. J'essaie de déboguer la façon dont les types sont calculés par le compilateur TypeScript.

Gars
la source
Utilisez simplement un bon IDE, instanciez votre type et survolez la valeur dans le fichier source ouvert dans votre éditeur. Y a-t-il des informations supplémentaires que vous manquez en utilisant cette suggestion?
Patrick Roberts
@PatrickRoberts - merci pour la réponse. Quand je fais cela, il pointe vers un type complexe qui a des types conditionnels imbriqués. Cela pointe à son tour vers un autre type complexe similaire et il continue et parfois il se ramifie d'une manière qui n'est pas évidente. Essayer de trouver comment déboguer pourquoi cette branche de construction de type se produit.
Guy
1
Je pense que votre question bénéficierait d'un exemple concret pour le démontrer. J'ai également rencontré la situation que vous décrivez auparavant, mais généralement je trouve que la solution consiste à réécrire les types de sorte qu'ils soient soit plus opaques (par exemple, un générique interfaceavec un nom de conteneur auto-documenté au lieu d'un générique typequi tente d'étendre son définition dans l'info-bulle de l'EDI) ou simplement refactoriser la source pour éviter toute surutilisation de types conditionnels complexes.
Patrick Roberts
@PatrickRoberts essayant de mettre à jour ce référentiel vers Hapi / Joi @ 16 et de déboguer la génération de type est ce qui a conduit à cette question. github.com/TCMiranda/joi-extract-type
Guy
@PatrickRoberts c'est le problème spécifique de la mise à niveau elle-même pour le contexte. github.com/TCMiranda/joi-extract-type/issues/22
Guy

Réponses:

1

Il n'y a pas de mécanisme intégré en tapuscrit pour déconnecter les informations souhaitées en question. Cependant, si vous êtes intéressé à comprendre le travail interne, voici l'endroit dans le code source où la résolution effective des types conditionnels se produit.

Jetez un oeil à ces endroits en checker.ts.

ln: 13258 instantiateTypeWorker()
ln: 12303 getConditionalType()
ln: 12385 getTypeFromConditionalTypeNode()
ln: 12772getTypeFromTypeNode()


Vous trouverez ci-joint un plug-in dactylographié à moitié fait que j'ai assemblé négligemment. Il déconnecte la structure des données brutes d'un ConditionalType. Pour comprendre cette structure, vérifiez types.ts ln: 4634.

L'UX de ce plugin est terrible, mais cette structure vous indique comment dactylographié décide de la valeur finale d'un type conditionnel.

Quelques instructions ennuyeusement détaillées pour faire fonctionner ce plugin:

  1. mkdir my-ts-plugin && cd my-ts-plugin
  2. touch package.json et écris { "name": "my-ts-plugin", "main": "index.js" }
  3. yarn add typescript fast-safe-stringify
  4. copiez-collez cet extrait dans index.ts, utilisez tsc pour le compilerindex.js
  5. yarn link
  6. maintenant cddans le répertoire de votre propre projet ts, exécutezyarn link my-ts-plugin
  7. ajouter { "compilerOptions": { "plugins": [{ "name": "my-ts-plugin" }] } }à votretsconfig.json
  8. ajouter à l'espace de travail en définissant (.vscode/settings.json)cette ligne:{ "typescript.tsdk": "<PATH_TO_YOUR_TS_PROJECT>/node_modules/typescript/lib" }
  9. ouvrez la palette de commandes vscode et exécutez:
    1. TypeScript: Select TypeScript Version... -> Use Workspace Version
    2. TypeScript: Restart TS Server
    3. TypeScript: Open TS Server Log
  10. vous devriez voir le plug-in se déconnecter "PLUGIN UP AND RUNNING", maintenant ouvrir un fichier de code ts et survoler la souris vers un nœud de type conditionnel, vous devriez voir une structure de données loooooong json ajoutée au fichier journal.
hackape
la source
Merci pour ça @hackape. Je l'ai piraté et je peux produire des journaux qui sont intéressants et répertorier à peu près ce que je vois de manière interactive lorsque j'utilise VSCode, donc cela ne m'a pas beaucoup éloigné de l'endroit où j'étais. De bonnes instructions sur la façon de faire fonctionner ce plugin.
Guy
Je t'ai donné la prime. Même si cela ne m'a pas amené à la solution, je pense qu'avec plus d'efforts de ma part pour modifier ce plugin, je pourrais probablement y arriver et je ne peux pas imaginer qu'il y ait une meilleure solution à cela dans un avenir proche. Merci pour votre aide et vos efforts!
Guy
1
@Guy Merci pour la générosité. J'ai donc passé quelques heures de plus hier à essayer d'obtenir un résultat plus utile. Tu as raison. La structure de données ci-dessus capture l'objet AST-ish de la chaîne de type conditionnelle, mais c'est juste le résultat analysé, pas le résultat évalué. En ce qui concerne le "pourquoi" ou la branche conditionnelle que le résolveur de type prend lors de l'évaluation, il nécessite de vider les résultats de toutes les étapes intermédiaires, un peu comme mettre un debuggeren pause quelque part puis regarder manuellement à travers les étendues locales dans les piles d'appels.
Hackape
1
Je modifié le getConditionalType()en checker.tsfaire un tapuscrit de construction personnalisée, l' insertion d' une logique d'effets secondaires pour vider les informations intermédiaires le long du chemin. Et cette fois, j'ai obtenu quelque chose d'un peu plus utile. Je vais nettoyer mon code et y attacher un peu plus tard.
Hackape
1
@Guy the gist is here
hackape