Exportation typographique vs exportation par défaut

273

Quelle est la différence dans Typescript entre exportet default export. Dans tous les tutoriels, je vois des gens exporting dans leurs classes et je ne peux pas compiler mon code si je n'ajoute pas le defaultmot - clé avant d'exporter.

De plus, je n'ai trouvé aucune trace du mot-clé d'exportation par défaut dans la documentation officielle de frappe .

export class MyClass {

  collection = [1,2,3];

}

Ne compile pas. Mais:

export default class MyClass {

  collection = [1,2,3];

}

Est-ce que.

L'erreur est: error TS1192: Module '"src/app/MyClass"' has no default export.

fos.alex
la source
Cela pourrait aider: stackoverflow.com/q/32236163/218196
Felix Kling
3
Quelques lectures légères sur le sujet. Cela pourrait aider si vous montrez comment vous importez cette classe, je pense que c'est là que l'erreur se produit (vous devez probablement modifier la syntaxe d'importation pour corriger le scénario d'erreur).
Sunil D.
5
"export" et "export default" ne sont pas du tout TypeScript - ils sont ES6.
Sensei James

Réponses:

460

Export par défaut ( export default)

// MyClass.ts -- using default export
export default class MyClass { /* ... */ }

La principale différence est que vous ne pouvez avoir qu'une seule exportation par défaut par fichier et que vous l'importez comme ceci:

import MyClass from "./MyClass";

Vous pouvez lui donner le nom que vous voulez. Par exemple, cela fonctionne bien:

import MyClassAlias from "./MyClass";

Exportation nommée ( export)

// MyClass.ts -- using named exports
export class MyClass { /* ... */ }
export class MyOtherClass { /* ... */ }

Lorsque vous utilisez une exportation nommée, vous pouvez avoir plusieurs exportations par fichier et vous devez importer les exportations entourées d'accolades:

import { MyClass } from "./MyClass";

Remarque: l'ajout d'accolades corrige l'erreur que vous décrivez dans votre question et le nom spécifié dans les accolades doit correspondre au nom de l'exportation.

Ou dites que votre fichier a exporté plusieurs classes, alors vous pouvez importer les deux comme ceci:

import { MyClass, MyOtherClass } from "./MyClass";
// use MyClass and MyOtherClass

Ou vous pouvez donner à l'un d'eux un nom différent dans ce fichier:

import { MyClass, MyOtherClass as MyOtherClassAlias } from "./MyClass";
// use MyClass and MyOtherClassAlias

Ou vous pouvez importer tout ce qui est exporté en utilisant * as:

import * as MyClasses from "./MyClass";
// use MyClasses.MyClass and MyClasses.MyOtherClass here

Lequel utiliser?

Dans ES6, les exportations par défaut sont concises car leur cas d'utilisation est plus courant ; cependant, lorsque je travaille sur du code interne à un projet en TypeScript, je préfère utiliser les exportations nommées plutôt que les exportations par défaut presque tout le temps car cela fonctionne très bien avec le refactoring de code. Par exemple, si vous exportez par défaut une classe et renommez cette classe, il ne renommera que la classe dans ce fichier et aucune des autres références dans d'autres fichiers. Avec les exportations nommées, il renommera la classe et toutes les références à cette classe dans tous les autres fichiers.

Il joue également très bien avec les fichiers barrel (fichiers qui utilisent les export *exportations d' espace de noms - pour exporter d'autres fichiers). Un exemple de ceci est montré dans la section "exemple" de cette réponse .

Notez que mon opinion sur l'utilisation d'exportations nommées même lorsqu'il n'y a qu'une seule exportation est contraire au manuel TypeScript - voir la section "Red Flags". Je pense que cette recommandation ne s'applique que lorsque vous créez une API à utiliser par d'autres personnes et que le code n'est pas interne à votre projet. Lorsque je conçois une API pour les utilisateurs, j'utilise une exportation par défaut pour que les utilisateurs puissent le faire import myLibraryDefaultExport from "my-library-name";. Si vous n'êtes pas d'accord avec moi à ce sujet, j'aimerais entendre votre raisonnement.

Cela dit, trouvez ce que vous préférez! Vous pouvez utiliser l'un, l'autre ou les deux en même temps.

Points supplémentaires

Une exportation par défaut est en fait une exportation nommée avec le nom default, donc si le fichier a une exportation par défaut, vous pouvez également importer en faisant:

import { default as MyClass } from "./MyClass";

Et prenez note que ces autres façons d'importer existent: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports
David Sherret
la source
3
qu'est-il arrivé à import myAlias = require("./PathToFile")et avoir export = IInterfaceOrClassdans le dossier? Est-ce à l'ancienne maintenant?
BenCr
@BenCr oui, c'est la nouvelle voie es6
David Sherret
Pourquoi ne donnez-vous pas un exemple d'une «exportation nommée»?
Stato Machino
aws-sdk / clients / sns n'a pas d'export par défaut et lorsque j'accède à sns en utilisant import sns depuis '/ sns' je n'obtiens aucune exportation mais l'import myAlias ​​= require ("./ PathToFile") fonctionne. puis-je faire quelque chose pour le changer, importer des sns depuis '/ sns' sans faire de changements de source?
Jeson Dias
Si vous ne mettez pas explicitement le mot clé default, y aura-t-il toujours une exportation par défaut disponible dans ce fichier? si oui, quelles sont les règles.
Simon_Weaver
10

J'essayais de résoudre le même problème, mais j'ai trouvé un conseil intéressant de Basarat Ali Syed , de la renommée de TypeScript Deep Dive , selon lequel nous devrions éviter la export defaultdéclaration générique pour une classe et plutôt ajouter la exportbalise à la déclaration de classe. La classe importée doit plutôt être répertoriée dans la importcommande du module.

C'est-à-dire: au lieu de

class Foo {
    // ...
}
export default Foo;

et le simple import Foo from './foo';dans le module qui importera, on devrait utiliser

export class Foo {
    // ...
}

et import {Foo} from './foo'chez l'importateur.

La raison en est les difficultés de refactorisation des classes et le travail supplémentaire pour l'exportation. Le message original de Basarat est en export defaultpeut entraîner des problèmes

Hilton Fernandes
la source
0

Voici un exemple avec l'exportation d'objet simple.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

Dans le fichier principal (à utiliser lorsque vous ne voulez pas et n'avez pas besoin de créer de nouvelle instance) et que ce n'est pas global, vous ne l'importerez que lorsque cela sera nécessaire:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
Nikola Lukic
la source