Exportação datilografada vs. exportação padrão

273

Qual é a diferença em Typcript entre exporte default export. Em todos os tutoriais, vejo pessoas em exportsuas classes e não consigo compilar meu código se não adicionar a defaultpalavra - chave antes de exportar.

Além disso, não encontrei nenhum rastro da palavra-chave de exportação padrão na documentação oficial datilografada .

export class MyClass {

  collection = [1,2,3];

}

Não compila. Mas:

export default class MyClass {

  collection = [1,2,3];

}

Faz.

O erro é: error TS1192: Module '"src/app/MyClass"' has no default export.

fos.alex
fonte
Isso pode ajudar: stackoverflow.com/q/32236163/218196
Felix Kling
3
Alguma leitura leve sobre o assunto. Pode ajudar se você mostrar como está importando essa classe, acredito que é onde o erro está ocorrendo (você provavelmente precisará alterar a sintaxe de importação para corrigir o cenário de erro).
Sunil D.
5
"export" e "export default" não são de todo o TypeScript - são o ES6.
Sensei James

Respostas:

460

Exportação padrão ( export default)

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

A principal diferença é que você pode ter apenas uma exportação padrão por arquivo e importá-la da seguinte maneira:

import MyClass from "./MyClass";

Você pode dar o nome que quiser. Por exemplo, isso funciona bem:

import MyClassAlias from "./MyClass";

Exportação nomeada ( export)

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

Ao usar uma exportação nomeada, você pode ter várias exportações por arquivo e precisa importar as exportações entre chaves:

import { MyClass } from "./MyClass";

Nota: A adição de chaves corrigirá o erro que você está descrevendo na sua pergunta e o nome especificado nas chaves precisa corresponder ao nome da exportação.

Ou diga que seu arquivo exportou várias classes, então você pode importar as duas coisas assim:

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

Ou você pode dar a um deles um nome diferente neste arquivo:

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

Ou você pode importar tudo o que é exportado usando * as:

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

Qual usar?

No ES6, as exportações padrão são concisas porque seu caso de uso é mais comum ; no entanto, quando estou trabalhando no código interno de um projeto no TypeScript, prefiro usar exportações nomeadas em vez de exportações padrão quase o tempo todo, porque funciona muito bem com a refatoração de código. Por exemplo, se você exportar uma classe por padrão e renomear essa classe, ela somente renomeará a classe nesse arquivo e não nenhuma das outras referências em outros arquivos. Com exportações nomeadas, ele renomeará a classe e todas as referências a essa classe em todos os outros arquivos.

Também funciona muito bem com arquivos barril (arquivos que usam exportações de namespace - export *para exportar outros arquivos). Um exemplo disso é mostrado na seção "exemplo" desta resposta .

Observe que minha opinião sobre o uso de exportações nomeadas, mesmo quando há apenas uma exportação, é contrária ao Manual do TypeScript - consulte a seção "Bandeiras vermelhas". Acredito que esta recomendação se aplique apenas quando você estiver criando uma API para outras pessoas usarem e o código não for interno ao seu projeto. Ao projetar uma API para uso das pessoas, utilizarei uma exportação padrão para que as pessoas possam fazer import myLibraryDefaultExport from "my-library-name";. Se você não concorda comigo sobre isso, eu adoraria ouvir seu raciocínio.

Dito isto, encontre o que você prefere! Você pode usar um, outro ou ambos ao mesmo tempo.

Pontos adicionais

Uma exportação padrão é na verdade uma exportação nomeada com o nome default; portanto, se o arquivo tiver uma exportação padrão, você também poderá importar fazendo:

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

E observe que existem outras maneiras de importar: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports
David Sherret
fonte
3
o que aconteceu com import myAlias = require("./PathToFile")e ter export = IInterfaceOrClassno arquivo? Isso é antiquado agora?
BenCr
@BenCr sim, esta é a nova forma ES6
David Sherret
Por que você não dá um exemplo de 'Exportação Nomeada'?
Stato Machino 14/03
O aws-sdk / clients / sns não possui exportações padrão e ao acessar sns usando sns de importação de '/ sns' não recebo exportação, mas a importação myAlias ​​= require ("./ PathToFile") funciona. posso fazer algo para alterá-lo importar sns de '/ sns' sem fazer alterações na origem?
Jeson Dias 25/10
Se você não colocar explicitamente a palavra-chave default, ainda haverá uma exportação padrão disponível nesse arquivo? Se sim, quais são as regras.
Simon_Weaver
10

Eu estava tentando resolver o mesmo problema, mas encontrei um conselho interessante de Basarat Ali Syed , da fama TypeScript Deep Dive , de que deveríamos evitar a export defaultdeclaração genérica de uma classe e, em vez disso, anexar a exportmarca à declaração da classe. A classe importada deve ser listada no importcomando do módulo.

Ou seja: em vez de

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

e o simples import Foo from './foo';no módulo que importará, deve-se usar

export class Foo {
    // ...
}

e import {Foo} from './foo'no importador.

O motivo disso são as dificuldades na refatoração de classes e o trabalho adicional para exportação. O post original de Basarat está em export defaultpode levar a problemas

Hilton Fernandes
fonte
0

Aqui está um exemplo com a exportação simples de objetos.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

No arquivo principal (use quando você não deseja e não precisa criar uma nova instância) e não é global, você importará isso apenas quando necessário:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
Nikola Lukic
fonte