Експорт машинопису відносно експорту за замовчуванням


272

Яка різниця в Typescript між exportта default export. У всіх навчальних посібниках я бачу людей, exportякі проводять свої заняття, і я не можу скласти свій код, якщо я не додаю defaultключове слово перед експортом.

Крім того, я не зміг знайти жодного сліду за замовчуванням для експорту ключового слова в офіційній документації на typecript .

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.



3
Деякі легкі читання по темі. Це може допомогти, якщо ви покажете, як ви імпортуєте цей клас, я вважаю, що тут виникає помилка (вам, ймовірно, потрібно змінити синтаксис імпорту, щоб виправити сценарій помилок).
Суніл Д.

5
"експортувати" та "експортувати за замовчуванням" взагалі не TypeScript - вони ES6.
Сенсей Джеймс

Відповіді:


458

Експорт за замовчуванням ( 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


Чому б не навести приклад "Іменованого експорту"?
Stato Machino

aws-sdk / clients / sns не має експорту за замовчуванням, і при доступі до sns за допомогою імпорту sns з '/ sns' я не отримую експорту, але імпорт myAlias ​​= вимагає ("./ PathToFile") працює. чи можу я щось зробити, щоб змінити імпорт sns з '/ sns', не вносячи змін у джерело?
Jeson Dias

Якщо ви чітко не введете ключове слово 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) );
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.