J'ai quelques fichiers TypeScript:
MyClass.ts
class MyClass {
constructor() {
}
}
export = MyClass;
MyFunc.ts
function fn() { return 0; }
export = fn;
MyConsumer.ts
import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();
Cela me donne des erreurs lorsque j'essaye d'utiliser new
Le module "MyClass" se résout en une entité non-module et ne peut pas être importé à l'aide de cette construction.
et en essayant d'appeler fn()
Impossible d'appeler une expression dont le type n'a pas de signature d'appel.
Ce qui donne?
typescript
ecmascript-6
es6-modules
Ryan Cavanaugh
la source
la source
javascript
tant que balise principale et de laisserecmascript-6
, car la balise principale ici esttypescript
. La question suppose à tort queexport =
(une fonction TS) peut être associée àimport ... from
, alors qu'elle devrait l'êtreimport =
. Il s'agit essentiellement d'import / export de module ES6 vs CJS / AMD.Réponses:
Pourquoi ça ne marche pas
Il s'agit d'une
import
syntaxe de style ES6 / ES2015 . La signification exacte de ceci est "Prenez l' objet d'espace de noms du module chargé./MyClass
et utilisez-le localement commeMC
". Notamment, l '" objet d'espace de noms de module " consiste uniquement en un objet simple avec des propriétés. Un objet module ES6 ne peut pas être appelé en tant que fonction ou avecnew
.Pour le répéter: un objet d'espace de noms de module ES6 ne peut pas être appelé en tant que fonction ou avec
new
.La chose que vous
import
utilisez à* as X
partir d'un module est définie pour n'avoir que des propriétés. Dans CommonJS de niveau inférieur, cela peut ne pas être entièrement respecté, mais TypeScript vous indique quel est le comportement défini par la norme.Qu'est-ce qui fonctionne?
Vous devrez utiliser la syntaxe d'importation de style CommonJS pour utiliser ce module:
Si vous contrôlez les deux modules, vous pouvez utiliser
export default
place:MyClass.ts
MyConsumer.ts
Je suis triste à ce sujet; Les règles sont stupides.
Cela aurait été bien d'utiliser la syntaxe d'importation ES6, mais maintenant je dois faire cette
import MC = require('./MyClass');
chose? C'est tellement 2013! Boiteux! Mais le deuil fait partie intégrante de la programmation. Veuillez passer à la cinquième étape du modèle Kübler-Ross: Acceptation.TypeScript ici vous dit que cela ne fonctionne pas, car cela ne fonctionne pas. Il y a des hacks (ajouter une
namespace
déclaration àMyClass
est un moyen populaire de prétendre que cela fonctionne), et ils pourraient fonctionner aujourd'hui dans votre bundler de module de niveau inférieur (par exemple, rollup), mais c'est illusoire. Il n'y a pas encore d'implémentation de module ES6 dans la nature, mais ce ne sera pas toujours vrai.Imaginez votre futur moi, en essayant de s'exécuter sur une implémentation de module ES6 native soignée et en constatant que vous vous êtes préparé à un échec majeur en essayant d'utiliser la syntaxe ES6 pour faire quelque chose que ES6 ne fait pas explicitement .
Je veux profiter de mon chargeur de module non standard
Peut-être avez-vous un chargeur de module qui crée «utilement» des
default
exportations lorsqu'il n'en existe pas. Je veux dire, les gens créent des normes pour une raison, mais ignorer les normes est parfois amusant et nous pouvons penser que c'est une bonne chose à faire.Remplacez MyConsumer.ts par:
Et spécifiez la
allowSyntheticDefaultImports
ligne de commande ou l'tsconfig.json
option.Notez que
allowSyntheticDefaultImports
cela ne change pas du tout le comportement d'exécution de votre code. C'est juste un indicateur qui indique à TypeScript que votre chargeur de module crée desdefault
exportations lorsqu'il n'en existe pas. Cela ne fera pas fonctionner comme par magie votre code dans nodejs alors que ce n'était pas le cas auparavant.la source
export = MyClass
? Ma seule option est de configurer mon modulecommonjs
et de continuer à rendre le monde pire en n'utilisant pas ES moderne?--esModuleInterop
, il est dit "Nous recommandons fortement de l'appliquer à la fois aux projets nouveaux et existants". À mon avis, cette réponse (et l' entrée / politique de la FAQ dansDefinitelyTyped
ce lien ici) devrait être modifiée pour refléter la nouvelle position.TypeScript 2.7 introduit le support en émettant de nouvelles méthodes d'assistance: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form- commonjs-modules-avec --- esmoduleinterop
Donc, dans tsconfig.json, ajoutez ces deux paramètres:
Et maintenant, vous pouvez utiliser:
la source
esModuleInterop
j'ai utiliséresolveJsonModule
avec votre autre suggestion d'utilisationallowSyntheticDefaultImports
et cela a fonctionné pour moi.Ajouter mes 2 cents ici au cas où quelqu'un d'autre aurait ce problème.
Ma façon de contourner le problème sans modifier
tsconfig.json
(ce qui peut être problématique dans certains projets), j'ai simplement désactivé la règle pour en ligne.import MC = require('./MyClass'); // tslint:disable-line
la source
J'ai eu cette erreur en essayant d'inclure un package anti-rebond npm dans mon projet.
Lorsque j'ai essayé la solution acceptée ci-dessus, j'ai eu une exception:
Cela a fini par fonctionner:
la source