20

Je suis aux prises avec ce problème depuis quelques heures et je n'arrive pas à trouver quoi que ce soit sur Internet qui expliquerait clairement ce concept soi-disant simple.Comment configurer des interfaces globales personnalisées (fichiers .d.ts) pour TypeScript?

Je travaille actuellement sur un projet ReactJS qui utilise Webpack2 et TypeScript. Tout fonctionne parfaitement à part une chose - je ne peux pas trouver un moyen de déplacer les interfaces que j'ai écrites moi-même dans des fichiers séparés afin qu'ils soient visibles pour l'ensemble de l'application. À des fins de prototypage, j'avais d'abord des interfaces définies dans les fichiers qui les utilisaient mais j'ai fini par en ajouter quelques-unes qui étaient nécessaires dans plusieurs classes et c'est là que tous les problèmes ont commencé. Peu importe les changements que je fais à mon tsconfig.json et peu importe où je mets les fichiers mon IDE et Webpack se plaignent tous deux de ne pas être en mesure de trouver des noms (Could not find name 'IMyInterface').

Voici mon fichier actuel tsconfig.json:

{ 
    "compilerOptions": { 
    "baseUrl": "src", 
    "outDir": "build/dist", 
    "module": "commonjs", 
    "target": "es5", 
    "lib": [ 
     "es6", 
     "dom" 
    ], 
    "typeRoots": [ 
     "./node_modules/@types", 
     "./typings" 
    ], 
    "sourceMap": true, 
    "allowJs": true, 
    "jsx": "react", 
    "moduleResolution": "node", 
    "rootDir": "src", 
    "forceConsistentCasingInFileNames": true, 
    "noImplicitReturns": true, 
    "noImplicitThis": true, 
    "noImplicitAny": false, 
    "strictNullChecks": true, 
    "suppressImplicitAnyIndexErrors": true, 
    "noUnusedLocals": true 
    }, 
    "exclude": [ 
    "node_modules", 
    "build", 
    "scripts", 
    "acceptance-tests", 
    "webpack", 
    "jest", 
    "src/setupTests.ts" 
    ], 
    "types": [ 
    "typePatches" 
    ] 
} 

Comme vous pouvez le voir, mon tsconfig.json est à la racine du répertoire du projet, toutes les sources est ./src, je posai mes fichiers personnalisés .d.ts dans ./typings et l'a inclus en typeRoots.

Je l'ai testé avec TypeScript 2.1.6 et 2.2.0 et ne fonctionne pas.

Une façon de tout le travail est de déplacer mon répertoire typings dans src puis import {IMyInterface} from 'typings/blah' mais cela ne se sent pas bien pour moi que ce n'est pas quelque chose que je dois utiliser. Je veux que ces interfaces soient simplement "magiquement" disponibles tout au long de mon application.

Edit: Voici un exemple de fichier app.d.ts:

interface IAppStateProps { 
} 

interface IAppDispatchProps { 
} 

interface IAppProps extends IAppStateProps, IAppDispatchProps { 
} 

Ai-je besoin de les export ou declare peut-être? J'espère que je ne dois pas les envelopper dans un espace de noms ?!

Répondre

34

Les «interfaces disponibles par la magie» ou les types globaux sont fortement déconseillés et devraient surtout être laissés à l'héritage. En outre, vous ne devez pas utiliser les fichiers de déclaration ambiants (par exemple, les fichiers d.ts) pour le code que vous écrivez. Ils sont destinés à remplacer le code externe non-typé (en remplissant essentiellement les types dactylographiés dans le code js afin que vous puissiez mieux l'intégrer avec javascript).

Pour le code que vous écrivez, vous devez utiliser des fichiers .ts simples pour définir vos interfaces et types.

Alors que les types globaux sont déconseillés, la réponse à votre problème est qu'il existe deux types de fichiers .ts dans Typescript. Ceux-ci sont appelés scripts et modules.

Tout ce qui se trouve dans un script sera global. Donc, si vous définissez vos interfaces dans un script, il sera disponible globalement dans votre application (tant que le script est inclus dans la compilation soit par ///<reference path=""> soit par files:[] ou includes:[] ou par défaut **/*.ts dans votre tsconfig.json.

L'autre type de fichier est 'module', et tout élément d'un module sera privé au module. Si vous exportez quelque chose d'un module, il sera disponible pour les autres modules si ces autres modules ont choisi de l'importer.

Qu'est-ce qui fait qu'un fichier .ts est un "script" ou un "module"? Eh bien .... si vous utilisez import/export n'importe où dans le fichier, ce fichier devient un "module". S'il n'y a pas d'instructions import/export, il s'agit d'un script global. Je suppose que vous avez utilisé par inadvertance import ou export dans vos déclarations et l'avez transformé en un module, qui a rendu toutes vos interfaces privées dans ce module. Si vous souhaitez qu'ils soient globaux, assurez-vous que vous n'utilisez pas d'instructions d'importation/exportation dans votre fichier.

+0

Vous avez absolument raison! Il s'est avéré que mon problème était (comme vous l'avez suggéré) que j'importais des classes/interfaces d'autres fichiers dans mes fichiers de déclaration. Dès que j'ai enlevé ces importations et que je n'ai laissé que des déclarations propres à 'l'interface Foo {}', tout a fonctionné. En ce qui concerne les globales - je vois complètement pourquoi avoir des déclarations magiquement disponibles est une mauvaise pratique et envisage de passer à un module personnalisé (en fait essayé 'declare module MyApp {export interface Foo {}}' et pourrait importer avec succès 'import {{Foo} from 'MyApp'') mais pour l'instant la magie fonctionne pour moi :) – Andris

+0

Merci, vos réponses beaucoup! – jasonslyvia