Tapuscrit 2: personnalisé typings pour typée module npm

après avoir essayé les suggestions postées dans autres endroits , je me trouve incapable d'obtenir un projet dactylographié en cours d'exécution qui utilise un module NPM non typé. Ci-dessous est un exemple minimal et les étapes que j'ai essayé.

pour cet exemple minimal, nous ferons comme si lodash n'avait pas de définition de type existante. Ainsi, nous ignorerons le paquet @types/lodash et essaierons d'ajouter manuellement son fichier de frappe lodash.d.ts à notre projet.

structure de dossiers

  • node_modules
    • lodash
  • src
    • foo.ts
  • typographies
    • personnalisé
      • lodash.d.ts
    • global
    • de l'index.d.ts
  • Paquet
  • .json
  • tsconfig.json
  • typographies.json

suivant, les fichiers.

Fichier foo.ts

///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from 'lodash';

console.log('Weeee');

fichier lodash.d.ts est copié directement du paquet original @types/lodash .

Fichier index.d.ts

/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />

Fichier package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "typings": "./typings/index.d.ts",
  "dependencies": {
    "lodash": "^4.16.4"
  },
  "author": "",
  "license": "ISC"
}

Fichier tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "typeRoots" : ["./typings"],
    "types": ["lodash"]
  },
  "include": [
    "typings/**/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

Fichier typings.json

{
    "name": "TestName",
    "version": false,
    "globalDependencies": {
        "lodash": "file:typings/custom/lodash.d.ts"
    }
}

comme vous pouvez le voir, j'ai essayé de nombreuses façons différentes d'importer des typographies:

  1. en l'important directement dans foo.ts
  2. Par un typings propriété package.json
  3. en utilisant typeRoots dans tsconfig.json avec un fichier typings/index.d.ts
  4. en utilisant un types explicite dans tsconfig.json
  5. en incluant le répertoire types dans tsconfig.json
  6. en faisant un fichier personnalisé typings.json et en exécutant typings install

pourtant, quand j'exécute le script:

E:tempts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

Qu'est-ce que je fais de mal?

59
demandé sur Community 2016-10-24 18:29:46

2 réponses

malheureusement, ces choses ne sont pas très bien documentées pour le moment, mais même si vous avez pu le faire fonctionner, revoyons votre configuration pour que vous compreniez ce que chaque partie fait et comment elle est liée à la façon dont le texte dactylographié traite et charge les typographies.

voyons D'abord l'erreur que vous recevez:

error TS2688: Cannot find type definition file for 'lodash'.

cette erreur ne provient pas de vos importations ou références ou de votre tentative d'utiliser lodash n'importe où dans vos fichiers ts. Il vient plutôt d'une mauvaise compréhension de la façon d'utiliser les propriétés typeRoots et types , donc allons dans un peu plus de détails sur ceux-ci.

la chose au sujet des propriétés typeRoots:[] et types:[] est qu'elles sont et non façons générales de charger des fichiers de déclaration arbitraire ( *.d.ts ).

Ces deux propriétés sont directement liées à la nouvelle TS 2.0 qui permet d'emballer et de charger des déclarations dactylographiées de paquets NPM .

il est très important de comprendre que ces dossiers ne fonctionnent qu'avec des dossiers au format NPM (c.-à-d. un dossier contenant un paquet ).json ou de l'index.D. ts ).

la valeur par défaut pour typeRoots est:

{
   "typeRoots" : ["node_modules/@types"]
}

par défaut, cela signifie que le code typographique le dossier node_modules/@types et essayer de charger chaque sous-dossier qu'il y trouve comme un" paquet 15191010920 "npm .

il est important de comprendre que cela échouera si un dossier n'a pas une structure semblable à celle d'un paquet npm.

C'est ce qui se passe dans votre cas, et la source de votre erreur initiale.

vous avez commuté typogroot pour être:

{
    "typeRoots" : ["./typings"]
}

cela signifie que tapescript va maintenant scanner le dossier ./typings pour sous-dossiers et essayer de charger chaque sous-dossier qu'il trouve comme un module npm.

alors faisons comme si vous aviez typeRoots setup pour pointer ./typings mais n'aviez pas encore DE setup types:[] . Vous verriez probablement ces erreurs:

error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.

c'est parce que tsc numérise votre dossier ./typings et trouve les sous-dossiers custom et global . Il essaie ensuite de les interpréter comme une saisie de type paquet npm, mais il n'y a pas de index.d.ts ou package.json dans ces dossiers et donc vous obtenez l'erreur.

maintenant, parlons un peu de la propriété types: ['lodash'] que vous définissez. À quoi ça sert? Par défaut, typescript chargera tous les sous-dossiers qu'il trouve dans votre typeRoots . Si vous spécifiez une propriété types: , elle ne chargera que les des sous-dossiers.

dans votre cas, vous lui demandez de charger le dossier ./typings/lodash mais il n'existe pas. C'est pourquoi vous obtenez:

error TS2688: Cannot find type definition file for 'lodash'

résumons donc ce que nous avons appris. Dactylographié 2.0 introduit typeRoots et types pour le chargement des fichiers de déclaration emballés dans paquets npm . Si vous avez des typographies sur mesure ou des fichiers d.ts qui ne sont pas contenus dans un dossier suivant mnp paquet de conventions, alors ces deux nouvelles propriétés ne sont pas ce que vous voulez utiliser. Typescript 2.0 ne change pas vraiment comment ceux-ci seraient consommés. Vous avez juste à inclure ces fichiers dans votre compilation contexte dans l'une des nombreuses façons:

  1. l'incluant directement dans un fichier .ts : ///<reference path="../typings/custom/lodash.d.ts" />

  2. y Compris ./typings/custom/lodash.d.ts dans votre "1519390920 de la propriété".

  3. y Compris ./typings/index.d.ts dans votre "1519390920 de la propriété" (qui a ensuite récursivement comprend les autres typings.

  4. ajouter ./typings/** à votre includes:

avec un peu de chance, sur la base de cette discussion, vous pourrez dire pourquoi les changements que vous avez apportés à votre tsconfig.json ont fait fonctionner les choses à nouveau.

EDIT:

une chose que j'ai oublié de mentionner est que la propriété typeRoots et types ne sont réellement utiles que pour le chargement automatique des déclarations globales.

par exemple si vous

npm install @types/jquery

et vous utilisez le tsconfig par défaut, alors que le paquet jQuery types sera chargé automatiquement et $ sera disponible dans tous vos scripts wihtout devant faire autres ///<reference/> ou import

la propriété typeRoots:[] est destinée à ajouter des emplacements supplémentaires à partir desquels le type paquets sera chargé automatiquement.

le premier cas d'utilisation de la propriété types:[] est de désactiver le comportement de chargement automatique (en le positionnant sur un tableau vide), et ensuite seulement la liste des types spécifiques que vous voulez inclure globalement.

L'autre façon de la nouvelle directive ///<reference types="jquery" /> doit être utilisée pour les colis de type charge des différentes catégories typeRoots . Remarquez le types au lieu de path . Encore une fois, cela n'est utile que pour les fichiers de déclaration globale, généralement ceux qui ne font pas import/export .

maintenant, voici une des choses qui cause la confusion avec typeRoots . Rappelez-vous, j'ai dit que typeRoots est sur l'inclusion globale des modules. Mais @types/folder est également impliqué dans la résolution de module standard (quel que soit votre paramètre typeRoots ).

spécifiquement, l'importation explicite de modules contourne toujours tous les includes , excludes , files , typeRoots et types options. Alors quand vous faites:

import {MyType} from 'my-module';

toutes les propriétés mentionnées ci-dessus sont complètement ignorées. Les propriétés pertinentes pendant la résolution du module sont baseUrl , paths , et moduleResolution .

en gros, en utilisant la résolution de module node , il commencera à rechercher un nom de fichier my-module.ts , my-module.tsx , my-module.d.ts en commençant par le dossier indiqué par votre configuration baseUrl .

S'il ne trouve pas le fichier, alors il va chercher un dossier nommé my-module et puis rechercher un package.json avec une propriété typings , s'il y a une propriété package.json ou pas typings à l'intérieur lui dire quel fichier à charger il cherchera ensuite index.ts/tsx/d.ts dans ce dossier.

si ce n'est pas encore réussi, il va chercher ces mêmes choses dans le dossier node_modules à partir de votre baseUrl/node_modules .

de plus, s'il ne les trouve pas, il cherchera baseUrl/node_modules/@types pour toutes les mêmes choses.

S'il n'a toujours rien trouvé, il va commencer à aller dans le répertoire parent et chercher node_modules et node_modules/@types y. Il va continuer à monter les répertoires jusqu'à ce qu'il atteigne la racine de votre système de fichiers (même en obtenant des noeuds-modules en dehors de votre projet).

une chose que je veux souligner est que la résolution du module ignore complètement n'importe quel typeRoots que vous mettez. Ainsi, si vous avez configuré typeRoots: ["./my-types"] , cela ne sera pas recherché pendant la résolution explicite du module. Il sert seulement comme un dossier où vous pouvez mettre des fichiers de définition globale que vous voulez rendre disponibles à l'ensemble de l'application sans avoir besoin d'importer ou de référence.

enfin, vous pouvez outrepasser le comportement du module avec des mappages de chemin (i.e. la propriété paths ). Ainsi, par exemple, j'ai mentionné que n'importe quelle coutume typeRoots n'est pas consultée en essayant de résoudre un module. Mais si vous avez aimé, vous pouvez faire en sorte que ce comportement se produise ainsi:

"paths" :{
     "*": ["my-custom-types/*", "*"]
 }

ce n'est, pour toutes les importations qui correspondent à la gauche, essayez de modifier l'importation comme dans le côté droit avant d'essayer de l'inclure (le * sur le côté droit représente votre importation initiale de la chaîne. Par exemple si vous importez:

import {MyType} from 'my-types';

il essaierait d'abord l'importation comme si vous aviez écrit:

import {MyType} from 'my-custom-types/my-types'

et puis s'il ne trouvait pas il essaierait de nouveau wihout le préfixe (deuxième élément dans le tableau est juste * qui signifie l'importation initiale.

ainsi vous pouvez ajouter des dossiers supplémentaires pour rechercher des fichiers de déclaration personnalisés ou même des modules .ts personnalisés que vous voulez pouvoir import .

vous pouvez également créer des mappages personnalisés pour des modules spécifiques:

"paths" :{
   "*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
 }

cela vous permettrait de faire

import {MyType} from 'my-types';

mais ensuite lire ces types de some/custom/folder/location/my-awesome-types-file.d.ts

123
répondu dtabuenc 2017-10-18 11:57:29

Edit: périmé. Lire la réponse ci-dessus.

je ne comprends toujours pas, mais j'ai trouvé une solution. Utilisez le tsconfig.json suivant:

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "*": [
        "./typings/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

Supprimer typings.json et tout dans le dossier typings sauf lodash.d.ts . Supprimer aussi toutes les références ///... 151970920"

4
répondu Jodiug 2017-12-13 09:51:11