Esportazione dattiloscritta vs. esportazione predefinita


273

Qual'è la differenza in Typescript tra exporte default export. In tutti i tutorial vedo persone nelle exportloro classi e non posso compilare il mio codice se non aggiungo la defaultparola chiave prima dell'esportazione.

Inoltre, non ho trovato tracce della parola chiave di esportazione predefinita nella documentazione ufficiale dei dattiloscritti .

export class MyClass {

  collection = [1,2,3];

}

Non compilare. Ma:

export default class MyClass {

  collection = [1,2,3];

}

Fa.

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



3
Qualche lettura leggera sull'argomento. Potrebbe essere utile se mostri come stai importando questa classe, credo che sia lì che si sta verificando l'errore (probabilmente dovrai modificare la sintassi di importazione per correggere lo scenario di errore).
Sunil D.

5
"export" e "export default" non sono affatto TypeScript: sono ES6.
Sensei James,

Risposte:


460

Esportazione predefinita ( export default)

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

La differenza principale è che puoi avere solo un'esportazione predefinita per file e importarla in questo modo:

import MyClass from "./MyClass";

Puoi dargli il nome che preferisci. Ad esempio, funziona bene:

import MyClassAlias from "./MyClass";

Named Export ( export)

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

Quando si utilizza un'esportazione denominata, è possibile avere più esportazioni per file ed è necessario importare le esportazioni racchiuse tra parentesi graffe:

import { MyClass } from "./MyClass";

Nota: l'aggiunta delle parentesi graffe correggerà l'errore che stai descrivendo nella tua domanda e il nome specificato nelle parentesi graffe deve corrispondere al nome dell'esportazione.

Oppure dire che il file ha esportato più classi, quindi è possibile importare entrambi in questo modo:

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

Oppure potresti dare uno di loro un nome diverso in questo file:

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

Oppure puoi importare tutto ciò che viene esportato usando * as:

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

Quale usare?

In ES6, le esportazioni predefinite sono concise perché il loro caso d'uso è più comune ; tuttavia, quando sto lavorando su codice interno a un progetto in TypeScript, preferisco usare le esportazioni denominate anziché le esportazioni predefinite quasi sempre perché funziona molto bene con il refactoring del codice. Ad esempio, se si esporta in modo predefinito una classe e la rinomina, questa rinominerà solo la classe in quel file e non gli altri riferimenti in altri file. Con le esportazioni denominate rinominerà la classe e tutti i riferimenti a quella classe in tutti gli altri file.

Funziona anche molto bene con i file barrel (file che usano le export *esportazioni dello spazio dei nomi - per esportare altri file). Un esempio di questo è mostrato nella sezione "esempio" di questa risposta .

Nota che la mia opinione sull'uso delle esportazioni con nome anche quando c'è una sola esportazione è contraria al manuale di TypeScript: vedi la sezione "Bandiere rosse". Ritengo che questa raccomandazione si applichi solo quando si crea un'API da utilizzare per altre persone e il codice non è interno al progetto. Quando sto progettando un'API da usare per le persone, userò un'esportazione predefinita che le persone possono fare import myLibraryDefaultExport from "my-library-name";. Se non sei d'accordo con me sul fare questo, mi piacerebbe sentire il tuo ragionamento.

Detto questo, trova quello che preferisci! Potresti usare l'uno, l'altro o entrambi contemporaneamente.

Punti aggiuntivi

Un'esportazione predefinita è in realtà un'esportazione denominata con il nome default, quindi se il file ha un'esportazione predefinita, puoi anche importare:

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

E prendi nota che esistono altri modi per importare: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports

3
cosa è successo import myAlias = require("./PathToFile")e che hai export = IInterfaceOrClassnel file? È vecchio stile adesso?
BenCr

@BenCr sì, questo è il nuovo modo es6
David Sherret,

Perché non dai un esempio di "esportazione denominata"?
Stato Machino,

aws-sdk / clients / sns non ha esportazioni predefinite e quando accedo a sns usando import sns da '/ sns' non ottengo esportazione ma l'importazione myAlias ​​= Require ("./ PathToFile") funziona. posso fare qualcosa per cambiarlo importare sns da '/ sns' senza apportare modifiche alla fonte?
Jeson Dias,

Se non si inserisce esplicitamente la parola chiave default, nel file sarà comunque disponibile un'esportazione predefinita? in tal caso quali sono le regole.
Simon_Weaver,

10

Stavo cercando di risolvere lo stesso problema, ma ho trovato un consiglio interessante di Basarat Ali Syed , della fama DeepScript di TypeScript , che dovremmo evitare la export defaultdichiarazione generica per una classe e invece aggiungere il exporttag alla dichiarazione della classe. La classe importata dovrebbe invece essere elencata nel importcomando del modulo.

Cioè: invece di

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

e il semplice import Foo from './foo';nel modulo che verrà importato, si dovrebbe usare

export class Foo {
    // ...
}

e import {Foo} from './foo'nell'importatore.

La ragione di ciò sono le difficoltà nel refactoring delle classi e il lavoro aggiunto per l'esportazione. Il post originale di Basarat è in export defaultpuò portare a problemi


0

Ecco un esempio con l'esportazione di oggetti semplici.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

Nel file principale (utilizzare quando non si desidera e non è necessario creare una nuova istanza) e non è globale, questo verrà importato solo quando necessario:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.