【问题标题】:Typescript export vs. default export打字稿导出与默认导出
【发布时间】:2016-01-23 04:52:53
【问题描述】:

exportdefault export 在 Typescript 中有什么区别。在所有教程中,我看到有人export他们的课程,如果我在导出之前不添加default 关键字,我将无法编译我的代码。

另外,我在官方typescript documentation中找不到任何默认导出关键字的痕迹。

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.

【问题讨论】:

标签: javascript typescript ecmascript-6


【解决方案1】:

默认导出 (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 中,默认导出是简洁的,因为 their use case is more common;然而,当我在 TypeScript 中处理项目的内部代码时,我几乎总是更喜欢使用命名导出而不是默认导出,因为它非常适合代码重构。例如,如果您默认导出一个类并重命名该类,它只会重命名该文件中的类,而不会重命名其他文件中的任何其他引用。使用命名导出,它将重命名该类以及所有其他文件中对该类的所有引用。

它与barrel files(使用命名空间导出的文件——export *——导出其他文件)也能很好地配合。 this answer 的“示例”部分显示了这方面的一个示例。

请注意,我对即使只有一个导出也使用命名导出的观点与TypeScript Handbook 相悖——请参阅“危险信号”部分。我相信此建议仅适用于您创建供其他人使用的 API 并且代码不在您的项目内部的情况。当我设计供人们使用的 API 时,我将使用默认导出,以便人们可以使用import myLibraryDefaultExport from "my-library-name";。如果您不同意我这样做,我很想听听您的推理。

也就是说,找到你喜欢的!您可以同时使用一个、另一个或两者。

额外积分

默认导出实际上是名称为default 的命名导出,因此如果文件具有默认导出,那么您也可以通过以下方式导入:

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

并注意这些 other ways 要导入的存在:

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports

【讨论】:

  • import myAlias = require("./PathToFile") 和文件中有export = IInterfaceOrClass 发生了什么?现在是老式的吗?
  • @BenCr 是的,这是new es6 way
  • 为什么不举一个“命名导出”的例子?
  • aws-sdk/clients/sns 没有默认导出,当使用 import sns from '/sns' 访问 sns 时,我没有导出但 import myAlias = require("./PathToFile")作品。我可以做些什么来改变它 import sns from '/sns' 而不改变源吗?
  • 如果您没有明确输入关键字default,该文件中是否还有可用的默认导出?如果是这样,规则是什么。
【解决方案2】:

我试图解决同样的问题,但发现了 Basarat Ali Syed 提出的一个有趣的建议,它以 TypeScript Deep Dive 闻名,我们应该避免类的通用 export default 声明,并且而是将export 标记附加到类声明中。导入的类应该列在模块的import 命令中。

即:代替

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

以及要导入的模块中的简单import Foo from './foo';,应该使用

export class Foo {
    // ...
}

import {Foo} from './foo' 在导入器中。

原因是重构类的困难,以及额外的导出工作。 Basarat的原帖在Avoid Export Default

【讨论】:

    【解决方案3】:

    命名导出

    在 TS 中,您可以使用 export 关键字导出。然后可以通过import {name} from "./mydir"; 导入。这称为命名导出。一个文件可以导出多个命名的导出。此外,进口的名称必须与出口相匹配。例如:

    // foo.js file
    export class foo{}
    export class bar{}
    
    // main.js file in same dir
    import {foo, bar} from "./foo";
    

    以下替代语法也有效:

    // foo.js file
    function foo() {};
    function bar() {};
    export {foo, bar};
    
    // main.js file in same dir
    import {foo, bar} from './foo'
    

    默认导出

    我们也可以使用默认导出。每个文件只能有一个默认导出。导入默认导出时,我们省略了导入语句中的方括号。我们也可以为我们的导入选择我们自己的名称。

    // foo.js file
    export default class foo{}
    
    // main.js file in same directory
    import abc from "./foo";
    

    这只是 JavaScript

    模块及其相关的关键字如importexportexport default 是JavaScript 结构,而不是打字稿。然而 typescript 为它添加了接口和类型别名的导出和导入。

    【讨论】:

      【解决方案4】:

      这是一个简单的对象导出示例。

      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) );
      

      【讨论】:

        猜你喜欢
        • 2017-02-06
        • 2016-02-10
        • 2019-12-11
        • 2017-09-23
        • 2021-02-07
        • 2018-04-17
        • 2020-05-17
        • 2021-11-24
        • 2020-04-13
        相关资源
        最近更新 更多