102 votes

TypeScript 2: typages personnalisés pour le module npm non typé

Après avoir essayé les suggestions posté dans d'autres endroits, je me trouve dans l'impossibilité d'obtenir un tapuscrit projet en cours d'exécution qui utilise un non MNP module. Ci-dessous est un exemple minimal et les étapes que j'ai essayé.

Pour cet exemple minimal, nous allons faire semblant qu' lodash n'ont pas d'existant définitions de type. En tant que tel, nous allons ignorer le paquet @types/lodash et essayez d'ajouter manuellement son typings fichier lodash.d.ts de notre projet.

Structure de dossier

  • node_modules
    • lodash
  • src
    • foo.ts
  • typings
    • personnalisé
      • lodash.d.ts
    • mondial
    • index.d.ts
  • package.json
  • tsconfig.json
  • typings.json

Ensuite, 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 à partir de l'original @types/lodash package.

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é beaucoup de différentes manières d'importer des typings:

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

Pourtant, quand je lance la Machine:

E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

Ce que je fais mal?

227voto

dtabuenc Points 2368

Malheureusement, ces choses ne sont pas actuellement très bien documenté, mais même si vous étiez en mesure d'obtenir ce travail, nous allons aller sur votre configuration, pour que vous compreniez ce que chaque partie est en train de faire et comment il se rapporte à la façon dont la machine a ecrire des processus et des charges typings.

D'abord, revenons sur l'erreur que vous recevez:

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

Cette erreur est en fait ne vient pas de votre importations ou des références ou que vous essayez de les utiliser lodash n'importe où dans vos fichiers ts. C'est plutôt venir d'une mauvaise compréhension de la façon d'utiliser le typeRoots et types propriétés, nous allons donc aller dans un peu plus de détails sur ceux-ci.

La chose à propos de typeRoots:[] et types:[] propriétés, c'est qu'ils sont PAS à usage général façons de charger arbitraire déclaration (*.d.ts) des fichiers.

Ces deux propriétés sont directement liées à la nouvelle TS 2.0 qui permet d'emballage et de chargement de taper les déclarations de packages NPM.

C'est très important de comprendre, que ces travaux uniquement avec des dossiers dans MNP format (c'est à dire un dossier contenant un paquet.json ou de l'index.d.ts).

La valeur par défaut de typeRoots est:

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

Par défaut, cela signifie que la machine va aller dans l' node_modules/@types le dossier et essayez de charger tous les sous-dossiers qu'il y trouve comme un package npm.

Il est important de comprendre que ceci ne fonctionnera pas si un dossier n'a pas un package npm-forme de la structure.

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

Vous avez mis en typeRoot:

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

Cela signifie que la machine va maintenant rechercher la ./typings le dossier pour les sous-dossiers et essayez de charger chaque sous-dossier qu'il trouve comme un mécanisme national de prévention de module.

Donc, disons que vous avez juste eu typeRoots le programme d'installation de point d' ./typings , mais n'a pas encore d' types:[] configuration de la propriété. Vous seriez probablement voir ces erreurs:

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

C'est parce qu' tsc est la numérisation de votre ./typings le dossier et de trouver les sous-dossiers custom et global. Il est alors d'essayer de les interpréter comme mnp package-type de frappe, mais il n'y a pas d' index.d.ts ou package.json dans ces dossiers et si vous obtenez le message d'erreur.

Maintenant, nous allons parler un peu de l' types: ['lodash'] de la propriété en cours de réglage. À quoi ça sert? Par défaut, la machine se charge de tous les sous-dossiers qu'il trouve au sein de votre typeRoots. Si vous spécifiez un types: de la propriété, il ne charge que ceux des sous-dossiers.

Dans votre cas, vous avez à dire à la charge de l' ./typings/lodash le dossier, mais il n'existe pas. C'est pourquoi vous obtenez:

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

Donc, résumons ce que nous avons appris. Tapuscrit 2.0 a introduit typeRoots et types pour le chargement de la déclaration de fichiers emballés dans des packages npm. Si vous avez personnalisé typings ou unique lâche d.ts fichiers qui ne sont pas contenues dans un dossier suivant mnp paquet de conventions, alors ces deux nouvelles propriétés ne sont pas ce que vous voulez utiliser. Tapuscrit 2.0 ne change pas vraiment la manière dont elles seront consommées. Vous avez juste à inclure ces fichiers dans votre compilation contexte dans l'une des nombreuses façons:

  1. Directement dans un .tsle fichier: ///<reference path="../typings/custom/lodash.d.ts" />

  2. Y compris ./typings/custom/lodash.d.ts votre files: [] de la propriété.

  3. Y compris ./typings/index.d.ts votre files: [] de la propriété (qui a ensuite récursivement comprend les autres typings.

  4. L'ajout d' ./typings/** votre includes:

Espérons que sur la base de cette discussion, vous serez en mesure de dire pourquoi les changements que vous êtes fou de votre tsconfig.json fait les choses fonctionnent de nouveau.

EDIT:

Une chose que j'ai oublié de mentionner, c'est qu' typeRoots et types des biens sont vraiment seulement utile pour l' automatique de chargement de déclarations globales.

Par exemple, si vous

npm install @types/jquery

Et vous utilisez la valeur par défaut tsconfig, alors que jquery types de forfait sera automatiquement chargé et $ sera disponible tout au long de tous vos scripts sans avoir à faire toute autre ///<reference/> ou import

L' typeRoots:[] propriété est destinée à ajouter d'autres sites à partir d'où le type de paquets sera chargé frrom automatiquement.

L' types:[] de la propriété principale de cas d'utilisation est de désactiver le chargement automatique de comportement (en la plaçant dans un tableau vide), et ensuite seulement d'inscription de types spécifiques que vous souhaitez inclure à l'échelle mondiale.

L'autre façon de charger le type de paquets provenant de diverses typeRoots est d'utiliser le nouveau ///<reference types="jquery" /> directive. Avis de l' types au lieu de path. Encore une fois, ce n'est utile que pour la déclaration mondiale des fichiers, généralement ceux qui ne le font pas import/export.

Maintenant, voici l'une des choses qui cause de la confusion avec typeRoots. Rappelez-vous, j'ai dit que l' typeRoots est sur l'inclusion de modules. Mais @types/folder est également impliqué dans le module standard-définition (quel que soit votre typeRoots du réglage).

Plus précisément, explicitement l'importation des modules toujours contourne tous includes, excludes, files, typeRoots et types options. Ainsi, lorsque vous vous:

import {MyType} from 'my-module';

Toutes les propriétés mentionnées ci-dessus sont totalement ignorés. Les propriétés pertinentes au cours de résolution de module sont baseUrl, paths, et moduleResolution.

En gros, lors de l'utilisation d' node résolution de module, il va commencer à la recherche d'un nom de fichier my-module.ts, my-module.tsx, my-module.d.ts de départ dans le dossier pointé par votre baseUrl configuration.

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

Si ce n'est toujours pas de succès, il sera à la recherche de ces mêmes choses dans l' node_modules dossier à partir de votre baseUrl/node_modules.

En outre, si l'on ne trouve pas ces, il cherchera baseUrl/node_modules/@types pour tous les mêmes choses.

Si il n'a toujours pas trouver quoi que ce soit il va commencer le répertoire parent et de recherche, node_modules et node_modules/@types . Il va continuer à monter les répertoires jusqu'à ce qu'il atteigne la racine de votre système de fichiers (même l'obtention de nœud-modules à l'extérieur de votre projet).

Une chose que je veux souligner, c'est que le module de résolution ignore complètement tout typeRoots vous définissez. Donc, si vous avez configuré typeRoots: ["./my-types"], ce ne seront pas recherchés lors de l'explicite résolution de module. Il ne sert que d'un dossier dans lequel vous pouvez mettre de la définition globale des fichiers que vous souhaitez rendre disponibles à l'ensemble de l'application sans avoir besoin d'importer ou de référence.

Enfin, vous pouvez remplacer le module de comportement avec les mappages de chemin d'accès (c'est à dire l' paths de la propriété). Ainsi, par exemple, j'ai mentionné que de coutume typeRoots n'est pas consultée lorsque vous tentez de résoudre un module. Mais si vous avez aimé, vous pouvez faire ce comportement se passer comme ça:

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

Ce qu'il fait 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 ( * 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 faudrait d'abord essayer de l'importer comme si vous aviez écrit:

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

Et puis, si elle ne trouve pas qu'il allait essayer de nouveau sans le préfixe (deuxième élément du tableau est juste * ce qui signifie que l'importation initiale.

Ainsi, de cette façon, vous pouvez ajouter d'autres dossiers de recherche pour la déclaration en douane des fichiers ou même personnalisé .ts modules que vous voulez être en mesure d' import.

Vous pouvez également créer des mappages pour des modules spécifiques:

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

Ce serait vous faire

import {MyType} from 'my-types';

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

7voto

Jodiug Points 50

Edit: obsolète. Lisez la réponse ci-dessus.

Je ne comprends toujours pas cela, mais j'ai trouvé une solution. Utilisez les tsconfig.json :

 {
  "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 ce qui se trouve sous le dossier typings sauf lodash.d.ts . Supprimez également toutes les références ///...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X