J'ai des 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'essaie d'utiliser new
Le module "MyClass" est résolu en une entité autre que le 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 ne contient pas de signature d'appel.
Ce qui donne?
import * as MC from './MyClass';
Il s'agit de la syntaxe import
de style ES6/ES2015. La signification exacte est "Prenez le module objet d’espace de nommage chargé à partir de ./MyClass
et utilisez-le localement comme MC
". Notamment, le "module objet d'espace de nom " consiste uniquement en un objet brut avec des propriétés. Un objet de module ES6 ne peut pas être appelé en tant que fonction ou avec new
.
Pour le répéter: n objet d’espace de nommage de module ES6 ne peut pas être appelé en tant que fonction ou avec new
.
La chose que vous import
en utilisant * as X
à partir d'un module est définie pour n'avoir que des propriétés. Dans CommonJS, cela pourrait ne pas être entièrement respecté, mais TypeScript vous dit quel est le comportement défini par la norme.
Vous devez utiliser la syntaxe d'importation de style CommonJS pour utiliser ce module:
import MC = require('./MyClass');
Si vous contrôlez les deux modules, vous pouvez utiliser export default
à la place:
MyClass.ts
export default class MyClass {
constructor() {
}
}
MyConsumer.ts
import MC from './MyClass';
Il aurait été agréable d'utiliser la syntaxe d'importation ES6, mais maintenant je dois faire ceci import MC = require('./MyClass');
chose? C'est tellement 2013! Boiteux! Mais le chagrin est une partie normale de la programmation. Veuillez passer à la cinquième étape du modèle Kübler-Ross: Acceptance.
TypeScript vous dit ici que cela ne fonctionne pas, car cela ne fonctionne pas. Il y a des hacks (ajouter une déclaration namespace
à MyClass
est un moyen répandu de prétendre que cela fonctionne), et ils pourraient fonctionner aujourd'hui dans votre module de mise à niveau particulier bundler (par exemple rollup), mais cela est illusoire. Il n'y a pas encore d'implémentation de module ES6 dans la nature, mais cela ne sera pas vrai pour toujours.
Imaginez votre avenir, essayez de vous lancer sur une implémentation de module ESO natif neato et découvrez que vous vous êtes préparé à un échec majeur en essayant d'utiliser la syntaxe de ES6 pour faire quelque chose que ES6 n'a pas explicitement fait. .
Peut-être avez-vous un chargeur de modules qui "utilement" crée default
exportations quand il n'en existe pas Je veux dire, les gens font des normes pour une raison, mais les ignorer est parfois amusant et nous pouvons penser que c'est une bonne chose à faire.
Remplacez MyConsumer.ts par:
import A from './a';
Et spécifiez la ligne de commande allowSyntheticDefaultImports
ou tsconfig.json
.
Notez que allowSyntheticDefaultImports
ne modifie pas du tout le comportement d'exécution de votre code. C'est simplement un indicateur qui indique à TypeScript que votre chargeur de module crée default
exportations lorsqu'il n'en existe pas. Comme par magie, votre code ne fonctionnera pas dans nodejs.
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-with --- esmoduleinterop
Donc, dans tsconfig.json, ajoutez ces deux paramètres:
{
// Enable support for importing CommonJS modules targeting es6 modules
"esModuleInterop": true,
// When using above interop will get missing default export error from type check since
// modules use "export =" instead of "export default", enable this to ignore errors.
"allowSyntheticDefaultImports": true
}
Et maintenant, vous pouvez utiliser:
import MyClass from './MyClass';
Ajout de 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 poser problème dans certains projets), j'ai simplement désactivé la règle en ligne.
import MC = require('./MyClass'); // tslint:disable-line
J'ai eu cette erreur en essayant d'inclure un paquet npm debounce dans mon projet.
Lorsque j'ai essayé la solution acceptée ci-dessus, j'ai eu une exception:
L'affectation d'importation ne peut pas être utilisée pour cibler les modules ECMAScript. Envisagez d'utiliser "import * as ns de" mod "", "importer {a} de" mod "", "importer d de" mod "" ou un autre format de module.
Cela a fini par fonctionner:
import debounce from 'debounce'