Exportación mecanografiada versus exportación predeterminada

273

¿Cuál es la diferencia en mecanografiado entre exporty default export. En todos los tutoriales veo personas que exportimparten sus clases y no puedo compilar mi código si no agrego eldefault palabra clave antes de exportar.

Además, no pude encontrar ningún rastro de la palabra clave de exportación predeterminada en la documentación oficial del mecanografiado .

export class MyClass {

  collection = [1,2,3];

}

No compila Pero:

export default class MyClass {

  collection = [1,2,3];

}

Hace.

El error es: error TS1192: Module '"src/app/MyClass"' has no default export.

fos.alex
fuente
Esto podría ayudar: stackoverflow.com/q/32236163/218196
Felix Kling
3
Un poco de lectura ligera sobre el tema. Podría ayudar si muestra cómo está importando esta clase, creo que es donde está ocurriendo el error (probablemente necesite modificar la sintaxis de importación para corregir el escenario de error).
Sunil D.
55
"exportar" y "exportar por defecto" no son TypeScript, son ES6.
Sensei James

Respuestas:

460

Exportación predeterminada ( export default)

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

La principal diferencia es que solo puede tener una exportación predeterminada por archivo y la importa así:

import MyClass from "./MyClass";

Puedes darle el nombre que quieras. Por ejemplo, esto funciona bien:

import MyClassAlias from "./MyClass";

Exportación con nombre ( export)

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

Cuando utiliza una exportación con nombre, puede tener múltiples exportaciones por archivo y necesita importar las exportaciones entre llaves:

import { MyClass } from "./MyClass";

Nota: Agregar las llaves corregirá el error que está describiendo en su pregunta y el nombre especificado en las llaves debe coincidir con el nombre de la exportación.

O bien, digamos que su archivo exportó varias clases, luego podría importar ambas cosas así:

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

O podría dar a cualquiera de ellos un nombre diferente en este archivo:

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

O puede importar todo lo que se exporta usando * as:

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

¿Cuál usar?

En ES6, las exportaciones predeterminadas son concisas porque su caso de uso es más común ; sin embargo, cuando estoy trabajando en código interno de un proyecto en TypeScript, prefiero usar exportaciones con nombre en lugar de exportaciones predeterminadas casi todo el tiempo porque funciona muy bien con la refactorización de código. Por ejemplo, si exporta por defecto una clase y cambia el nombre de esa clase, solo cambiará el nombre de la clase en ese archivo y no ninguna de las otras referencias en otros archivos. Con exportaciones con nombre, cambiará el nombre de la clase y todas las referencias a esa clase en todos los demás archivos.

También funciona muy bien con archivos de barril (archivos que usan export *exportaciones de espacio de nombres para exportar otros archivos). Un ejemplo de esto se muestra en la sección "ejemplo" de esta respuesta .

Tenga en cuenta que mi opinión sobre el uso de exportaciones con nombre, incluso cuando solo hay una exportación, es contraria al Manual TypeScript: consulte la sección "Banderas rojas". Creo que esta recomendación solo se aplica cuando está creando una API para que la utilicen otras personas y el código no es interno de su proyecto. Cuando estoy diseñando una API para que la gente la use, usaré una exportación predeterminada para que la gente pueda hacer import myLibraryDefaultExport from "my-library-name";. Si no está de acuerdo conmigo en hacer esto, me encantaría escuchar su razonamiento.

Dicho esto, ¡encuentra lo que prefieres! Puede usar uno, el otro o ambos al mismo tiempo.

Puntos adicionales

Una exportación predeterminada es en realidad una exportación con nombre con el nombre default, por lo que si el archivo tiene una exportación predeterminada, también puede importar haciendo:

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

Y tenga en cuenta que existen otras formas 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
fuente
3
¿Qué pasó con import myAlias = require("./PathToFile")y teniendo export = IInterfaceOrClassen el archivo? ¿Eso está pasado de moda ahora?
BenCr
@BenCr sí, esta es la nueva forma es6
David Sherret
¿Por qué no da un ejemplo de una 'Exportación con nombre'?
Stato Machino
aws-sdk / clients / sns no tiene exportaciones predeterminadas y cuando accedo a sns usando import sns desde '/ sns' no obtengo exportación, pero la importación myAlias ​​= require ("./ PathToFile") funciona. ¿puedo hacer algo para cambiarlo? Importar sns desde '/ sns' sin hacer cambios en la fuente?
Jeson Dias
Si no pone explícitamente la palabra clave, ¿ defaulthabrá todavía una exportación predeterminada disponible en ese archivo? Si es así, ¿cuáles son las reglas?
Simon_Weaver
10

Estaba tratando de resolver el mismo problema, pero encontré un consejo interesante de Basarat Ali Syed , de la fama de inmersión profunda de TypeScript , de que deberíamos evitar la export defaultdeclaración genérica de una clase y, en su lugar, agregar la exportetiqueta a la declaración de la clase. La clase importada debería figurar en el importcomando del módulo.

Es decir: en lugar de

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

y lo simple import Foo from './foo';en el módulo que importará, uno debería usar

export class Foo {
    // ...
}

y import {Foo} from './foo'en el importador.

La razón de esto son las dificultades en la refactorización de las clases y el trabajo adicional para la exportación. La publicación original de Basarat export defaultpuede provocar problemas.

Hilton Fernandes
fuente
0

Aquí hay un ejemplo con la exportación de objetos simples.

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

En el archivo principal (se usa cuando no desea y no necesita crear una nueva instancia) y no es global, importará esto solo cuando sea necesario:

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