export
和 default 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.
默认导出 (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
我试图解决同样的问题,但发现了 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
命名导出
在 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
模块及其相关关键字(如 import
、export
和 export default
)是 JavaScript 结构,而不是 typescript。然而,打字稿添加了接口和类型别名的导出和导入。
这是简单对象导出的示例。
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) );
import myAlias = require("./PathToFile")
发生了什么并且文件中有export = IInterfaceOrClass
?现在是老式的吗?default
,那么该文件中是否还有可用的默认导出?如果是这样,规则是什么。