打字稿导出与默认导出

时间:2015-10-23 15:19:17

标签: typescript ecmascript-6

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.

4 个答案:

答案 0 :(得分:373)

默认导出(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

答案 1 :(得分:3)

我试图解决同样的问题,但是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的原始帖子在export default can lead to problems

答案 2 :(得分: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'

默认导出

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

// foo.js file
export default class foo{}

// main.js file in same directory
import abc from "./foo";

这只是JavaScript

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

答案 3 :(得分: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) );