typescript - 从另一个文件中导出一个 TypeScript 类,而不是在其中定义的

标签 typescript module

一段时间以来,我一直在尝试从我在一个地方编写的一个小库中导出类。我希望每个类都不知道它们是如何提供给外部的,但到目前为止我无法让它工作。

假设我有类 Foo

// lib/foo.ts
export class Foo {}

和类 Bar

// lib/bar.ts
export class Bar {}

现在我想让那些通过 MyModule 命名空间使用该包的人可用,这就是它变得棘手的地方。我不知道如何从类本身以外的其他地方定义的命名空间导出现有类。

显然,这行不通,因为它不是有效的 TypeScript:

// api.ts
import { Foo } from "./lib/foo";
import { Bar } from "./lib/bar";

export namespace MyModule {
    export Foo;

    export namespace MySubModule {
        export Bar;
    }
}

我已经找到了两种可能的解决方案,但两者都有其缺点。我可以定义一个变量并将类分配给它:

// api.ts
import { Foo as MyFoo } from "./lib/foo";
import { Bar as MyBar } from "./lib/bar";

export namespace MyModule {
    export const Foo = MyFoo;

    export namespace MySubModule {
        export const Bar = MyBar;
    }
}

这实际上允许我从外部位置创建该类的实例,如 new MyModule.MySubModule.Bar 但不会给我将它们用作类型的可能性,因为

let myBarInstance: MyModule.MySubModule.Bar;

会抛出一个 TypeScript 错误,指出

Module "path/to/module/api".MySubModule has no exported member 'Bar'

相反,我尝试使用 export type Bar = MyBar 而不是 const 并且这在说时有效

let myBarInstance: MyModule.MySubModule.Bar

另一方面,我自然无法实例化 MyModule.MySubModule.Bar,因为它只是一个类型别名。

对于 Foo 类,所有这些都是一样的。

有没有人对此有任何经验,我是否可能忽略了 TypeScript 提供的其他一些导出功能?

最佳答案

所以来自 TypeScript 团队的 Ryan Cavanaugh 非常友好 to answer my question在他们的 GitHub 上。

这实际上很简单:只需结合我想出的两种方法就可以了:

// api.ts
import { Foo as MyFoo } from "./lib/foo";
import { Bar as MyBar } from "./lib/bar";

export namespace MyModule {
    export const Foo = MyFoo;
    export type Foo = MyFoo;

    export namespace MySubModule {
        export const Bar = MyBar;
        export type Bar = MyBar;
    }
}

EDIT 2020: Now that I have some more years of TypeScript experience, I think I should provide an additional explanation why the code above works. This may be valuable information for new-ish TypeScript developers, because it touches a topic that is not often taught: TypeScript's separate type scope.

TypeScript 基本上维护了一个与 JavaScript 的变量范围平行的类型范围。这意味着您可以在同一文件中定义变量 foo 和类型 foo。它们甚至不需要兼容:

const foo = 'bar'
type foo = number

现在 TypeScript 中的类有点特别。如果你定义一个类 Foo 会发生什么,TypeScript 不仅创建一个变量 Foo(包含类对象本身)它还声明一个类型 Foo ,表示该类的一个实例。

类似地,当从另一个文件导入名称时,该名称下的任何定义的变量和类型都会被导入。这意味着在上面的代码中,MyFoo 包含 Foo 类对象以及来自 foo.ts< 的 Foo 类类型.

因此,如果我们通过编写 export const Foo = MyFooMyModule 命名空间内部重新导出 MyFoo,只有类 object 被导出(因为 const 只保存一个值,而不是一个类型)。同样,如果我们执行 export type Foo = MyFoo,则只会导出类 type

所以现在我们又回到了原点:由于独立的范围,以相同的名称导出值和类型是有效的。在某些情况下(如本例),它不仅有效而且必要。

关于typescript - 从另一个文件中导出一个 TypeScript 类,而不是在其中定义的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38655711/

相关文章:

java - 我如何访问在单独的 Web 应用程序中实现远程接口(interface)的 EJB?

javascript - 覆盖 @angular/pwa ngsw-worker.js

javascript - TypeScript:仅返回界面的一部分

javascript - 将动态数据传递给子组件

javascript - 找不到模块 '.../models/user' nodejs

module - 如何覆盖 Kohana 3 中的模块类?

module - 如何跨模块文件使用宏?

javascript - 正在搜索 Angular2 可视化表单编辑器或表单引擎,可以通过 GUI 或生成器或集中配置生成表单?

angular - 动态 SVG 组件

javascript - 如何将@providesModule与Jest和react-native一起使用