Eksport maszynopisu a domyślny eksport

272

Jaka jest różnica w maszynopisie między exporti default export. We wszystkich samouczkach widzę osoby uczestniczące w exportzajęciach i nie mogę skompilować kodu, jeśli nie dodam defaultsłowa kluczowego przed eksportem.

Poza tym nie mogłem znaleźć śladu domyślnego słowa kluczowego eksportu w oficjalnej dokumentacji maszynopisu .

export class MyClass {

  collection = [1,2,3];

}

Nie kompiluje się. Ale:

export default class MyClass {

  collection = [1,2,3];

}

Robi.

Błąd jest następujący: error TS1192: Module '"src/app/MyClass"' has no default export.

fos.alex
źródło
To może pomóc: stackoverflow.com/q/32236163/218196
Felix Kling
3
Niektóre lampka do czytania na ten temat. Może to pomóc, jeśli pokażesz, w jaki sposób importujesz tę klasę. Uważam, że tam właśnie występuje błąd (prawdopodobnie musisz zmienić składnię importu, aby naprawić scenariusz błędu).
Sunil D.
5
„eksport” i „domyślny eksport” wcale nie są TypeScript - są ES6.
Sensei James

Odpowiedzi:

458

Domyślny eksport ( export default)

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

Główną różnicą jest to, że możesz mieć tylko jeden domyślny eksport na plik i importujesz go w następujący sposób:

import MyClass from "./MyClass";

Możesz nadać mu dowolną nazwę. Na przykład działa to dobrze:

import MyClassAlias from "./MyClass";

Nazwany eksport ( export)

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

Gdy używasz nazwanego eksportu, możesz mieć wiele eksportów na plik i musisz zaimportować eksport otoczony nawiasami klamrowymi:

import { MyClass } from "./MyClass";

Uwaga: Dodanie nawiasów naprawi błąd opisany w pytaniu, a nazwa określona w nawiasach klamrowych musi pasować do nazwy eksportu.

Lub powiedzmy, że Twój plik wyeksportował wiele klas, a następnie możesz zaimportować obie:

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

Lub możesz nadać jednemu z nich inną nazwę w tym pliku:

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

Lub możesz zaimportować wszystko, co jest eksportowane, używając * as:

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

Którego użyć?

W ES6 domyślny eksport jest zwięzły, ponieważ ich przypadek użycia jest częstszy ; jednak, gdy pracuję nad kodem wewnętrznym projektu w TypeScript, prawie przez cały czas wolę używać nazwanego eksportu zamiast domyślnego eksportu, ponieważ działa bardzo dobrze przy refaktoryzacji kodu. Na przykład, jeśli domyślnie wyeksportujesz klasę i zmienisz jej nazwę, zmieni ona tylko nazwę klasy w tym pliku, a nie inne odniesienia w innych plikach. Dzięki nazwanym eksportom zmieni nazwę klasy i wszystkie odwołania do tej klasy we wszystkich innych plikach.

Bardzo dobrze gra również z plikami beczkowymi (pliki, które używają export *eksportu przestrzeni nazw - —w celu eksportu innych plików). Przykład tego pokazano w sekcji „przykład” tej odpowiedzi .

Zauważ, że moja opinia na temat korzystania z nazwanych eksportów, nawet jeśli istnieje tylko jeden eksport, jest sprzeczna z Podręcznikiem TypeScript - patrz sekcja „Czerwone flagi”. Uważam, że to zalecenie ma zastosowanie tylko wtedy, gdy tworzysz interfejs API dla innych osób, a kod nie jest wewnętrzny dla twojego projektu. Kiedy projektuję interfejs API dla ludzi, użyję domyślnego eksportu, aby ludzie mogli to zrobić import myLibraryDefaultExport from "my-library-name";. Jeśli nie zgadzasz się ze mną, chciałbym usłyszeć twoje uzasadnienie.

To powiedziawszy, znajdź to, co wolisz! Możesz użyć jednego, drugiego lub obu jednocześnie.

Dodatkowe punkty

Domyślny eksport jest tak naprawdę nazwanym eksportem o nazwie default, więc jeśli plik ma domyślny eksport, możesz również zaimportować, wykonując:

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

I zwróć uwagę, że istnieją inne sposoby importowania: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports
David Sherret
źródło
3
co stało się import myAlias = require("./PathToFile")i posiadające export = IInterfaceOrClassw pliku? Czy to już staroświecki?
BenCr 19.04.16
@BenCr tak, to jest nowy sposób es6
David Sherret
Dlaczego nie podasz przykładu „Nazwanego eksportu”?
Stato Machino
aws-sdk / client / sns nie ma domyślnego eksportu i podczas uzyskiwania dostępu do sns przy użyciu importu sns z '/ sns' nie otrzymuję eksportu, ale import myAlias ​​= wymaga („./ PathToFile”) działa. czy mogę zrobić coś, aby to zmienić importować sns z '/ sns' bez dokonywania zmian w źródle?
Jeson Dias,
Jeśli nie podasz wyraźnie słowa kluczowego, defaultczy w tym pliku będzie nadal dostępny domyślny eksport? jeśli tak, jakie są zasady.
Simon_Weaver
10

Próbowałem rozwiązać ten sam problem, ale znalazłem interesującą radę Basarata Ali Syeda dotyczącą sławy TypeScript Deep Dive , że powinniśmy unikać ogólnej export defaultdeklaracji dla klasy, a zamiast tego dołączyć exporttag do deklaracji klasy. Zaimportowana klasa powinna być zamiast tego wymieniona w importpoleceniu modułu.

To znaczy: zamiast

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

i prosty import Foo from './foo';w module, który zaimportuje, należy użyć

export class Foo {
    // ...
}

i import {Foo} from './foo'u importera.

Powodem tego są trudności w refaktoryzacji klas i dodatkowa praca na eksport. Oryginalny post Basatara jest w, export defaultmoże prowadzić do problemów

Hilton Fernandes
źródło
0

Oto przykład z prostym eksportem obiektów.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

W głównym pliku (użyj, gdy nie chcesz i nie musisz tworzyć nowego wystąpienia) i nie jest to globalne, zaimportujesz to tylko wtedy, gdy będzie to potrzebne:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
Nikola Lukic
źródło