Экспорт машинописного текста и экспорт по умолчанию

273

В чем разница между Typescript exportи default export. Во всех уроках я вижу людей, использующих exportих классы, и я не могу скомпилировать свой код, если не добавлю defaultключевое слово перед экспортом.

Кроме того, я не смог найти никаких следов ключевого слова экспорта по умолчанию в официальной машинописной документации .

export class MyClass {

  collection = [1,2,3];

}

Не компилируется. Но:

export default class MyClass {

  collection = [1,2,3];

}

Имеет ли.

Ошибка: error TS1192: Module '"src/app/MyClass"' has no default export.

fos.alex
источник
Это может помочь: stackoverflow.com/q/32236163/218196
Феликс Клинг
3
Некоторое легкое чтение по теме. Это может помочь, если вы покажете, как вы импортируете этот класс, я считаю, что именно здесь происходит ошибка (вам, вероятно, нужно изменить синтаксис импорта, чтобы исправить сценарий ошибки).
Сунил Д.
5
«export» и «export default» - это вообще не TypeScript, а ES6.
Сэнсэй Джеймс

Ответы:

460

Экспорт по умолчанию ( export default)

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

Основное отличие состоит в том, что вы можете иметь только один экспорт по умолчанию на файл и импортировать его следующим образом:

import MyClass from "./MyClass";

Вы можете дать ему любое имя. Например, это работает нормально:

import MyClassAlias from "./MyClass";

Именованный экспорт ( export)

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

Когда вы используете именованный экспорт, вы можете иметь несколько экспортов на файл, и вам нужно импортировать экспорт, заключенный в фигурные скобки:

import { MyClass } from "./MyClass";

Примечание. Добавление фигурных скобок исправит ошибку, которую вы описываете в своем вопросе, а имя, указанное в фигурных скобках, должно совпадать с именем экспорта.

Или, скажем, ваш файл экспортировал несколько классов, тогда вы можете импортировать оба так:

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

Или вы можете дать любому из них другое имя в этом файле:

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

Или вы можете импортировать все, что экспортируется, используя * as:

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

Какой использовать?

В ES6 экспорт по умолчанию сжат, потому что его вариант использования более распространен ; однако, когда я работаю над кодом, внутренним для проекта в TypeScript, я предпочитаю использовать именованные экспорты вместо экспортов по умолчанию почти все время, потому что это очень хорошо работает с рефакторингом кода. Например, если вы экспортируете класс по умолчанию и переименовываете этот класс, он будет переименовывать только класс в этом файле, а не любые другие ссылки в других файлах. С именованным экспортом он переименует класс и все ссылки на этот класс во всех других файлах.

Он также очень хорошо воспроизводится с бочковыми файлами (файлами, использующими export *экспорт пространства имен - для экспорта других файлов). Пример этого показан в разделе «пример» этого ответа .

Обратите внимание, что мое мнение об использовании именованных экспортов, даже если есть только один экспорт, противоречит Руководству по TypeScript - см. Раздел «Красные флаги». Я считаю, что эта рекомендация применима только тогда, когда вы создаете API для использования другими людьми, а код не является внутренним для вашего проекта. Когда я разрабатываю API для использования людьми, я использую экспорт по умолчанию, чтобы люди могли это делать import myLibraryDefaultExport from "my-library-name";. Если вы не согласны со мной по поводу этого, я хотел бы услышать ваше мнение.

Тем не менее, найти то, что вы предпочитаете! Вы можете использовать один, другой или оба одновременно.

Дополнительные очки

Экспорт по умолчанию на самом деле является именованным экспортом с именем default, поэтому, если файл имеет экспорт по умолчанию, вы также можете импортировать, выполнив:

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

И обратите внимание на следующие способы импорта: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports
Дэвид Шеррет
источник
3
что случилось import myAlias = require("./PathToFile")и что export = IInterfaceOrClassв файле? Это старомодно сейчас?
BenCr
@BenCr да, это новый путь es6
Дэвид Шеррет
Почему бы вам не привести пример «именного экспорта»?
Мачино,
У aws-sdk / clients / sns нет экспорта по умолчанию, и при доступе к sns с помощью импорта sns из '/ sns' я не получаю экспорт, но импорт myAlias ​​= require ("./ PathToFile") работает. Могу ли я сделать что-то, чтобы изменить его, импортировать sns из '/ sns' без внесения изменений в исходный код?
Джесон Диас
Если вы не укажете явно ключевое слово, defaultбудет ли в этом файле доступен экспорт по умолчанию? если так, каковы правила.
Simon_Weaver
10

Я пытался решить ту же проблему, но нашел интересный совет Басарата Али Сайеда , известного в TypeScript Deep Dive , о том, что нам следует избегать универсального export defaultобъявления для класса и вместо этого добавлять exportтег к объявлению класса. Импортированный класс должен быть указан в importкоманде модуля.

То есть вместо

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

и простой import Foo from './foo';в модуле, который будет импортировать, следует использовать

export class Foo {
    // ...
}

и import {Foo} from './foo'в импорте.

Причиной этого являются трудности в рефакторинге классов и добавленная работа на экспорт. Оригинальный пост Басарата в export defaultможет привести к проблемам

Хилтон Фернандес
источник
0

Вот пример с простым экспортом объектов.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

В основном файле (используйте, когда вы не хотите и не нужно создавать новый экземпляр), и он не является глобальным, вы импортируете его только тогда, когда это необходимо:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
Никола Лукич
источник