Предположим, у вас есть файл foo.ts
со следующим содержимым:
class Foo {
}
export default Foo;
Вы должны импортировать его (в bar.ts
), используя синтаксис ES6, как показано ниже:
import Foo from "./foo";
Здесь есть несколько проблем с удобством сопровождения:
- Если вы переименуете
Foo
вfoo.ts
, он не переименуется его вbar.ts
. - Если вам в конечном итоге потребуется экспортировать больше сущностей из
foo.ts
(что довольно распространенная ситуация), вам придется переделать синтаксис импорта.
По этой причине я рекомендую простой экспорт + деструктурированный импорт. Например foo.ts
:
export class Foo {
}
А затем:
import { Foo } from "./foo";
Ниже я также привожу еще несколько причин.
У экспорта по умолчанию очень низкая обнаруживаемость. Вы не можете исследовать модуль с помощью intellisense, чтобы узнать, есть ли у него экспорт по умолчанию или нет.
При экспорте по умолчанию вы ничего здесь не получите (может быть модуль экспортирует что-то по умолчанию / а может и нет ¯\_(ツ)_/¯
):
import /* здесь */ from 'something';
Без экспорта по умолчанию вы получите хорошее автодополнение intellisense:
import { /* здесь */ } from 'something';
Независимо от того, знаете вы об экспорте или нет, вы можете автодополнить импорт import {/*здесь*/} from "./foo";
. Это упрощает работу разработчиков.
Использование default
ужасные испытания для commonJS пользователей, которым приходится использовать const {default} = require('module/foo');
вместо const {Foo} = require('module/foo')
. Скорее всего, при импорте вы захотите переименовать экспорт по умолчанию
во что-нибудь другое.
Вы не получите опечаток, например, когда один разработчик пишет import Foo from "./foo";
, а другой пишет import foo from "./foo";
Автоматический импорт лучше всего работает c именованным экспортом. Вы используете Foo
, и автоматический импорт запишет import { Foo } from "./foo";
потому что это четко определенное имя, экспортированное из модуля. Некоторые инструменты будут пытаться волшебным образом прочитать и логически вывести имя и для экспорта по умолчанию, но такая магия уже не так надежна.
Реэкспорт является обычным явлением для корневого файла index
в пакетах npm и заставляет вас вручную указать экспорт по умолчанию, например export { default as Foo } from "./foo";
(экспорт по умолчанию) по сравнению с export * from "./foo"
(именованный экспорт).
Экспорт по умолчанию раскрывается с дополнительным default
при динамическом импорте
, например:
const HighCharts = await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');
HighCharts.default.chart('container', { ... }); // Обратите внимание `.default`
Лучше с именованным экспортом:
const {HighCharts} = await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');
HighCharts.chart('container', { ... }); // Обратите внимание `.default`
Достаточно одной инструкции для функции/класса, например:
export default function foo() {
}
Достаточно одной инструкции для безымянных / типизированых объектов, например:
export default {
notAFunction: 'Да, я не функция или класс',
soWhat: 'Экспорт сейчас *удален* из объявления'
};
Но в противном случае нужны две инструкции:
// Если вам нужна именованная константа (здесь `foo`) для локального использования ИЛИ нужно описать тип (здесь `Foo`)
const foo: Foo = {
notAFunction: 'Да, я не функция или класс',
soWhat: 'Экспорт сейчас *удален* из объявления'
};
export default foo;