我希望所有类都在基于库的项目中的命名空间下可用.

当涉及到将所有类放在一个名称空间下时,我遗漏了一个步骤.

假设我在两个文件夹中有两个类

  1. 第一步是将它们全部导出到一个库名或命名空间下
  2. 第二步是通过库名称或命名空间访问类,从而在测试文件夹中使用它们

Expectation/Question:能够通过公共库名访问和使用类,例如new mylib.Foo()new mylib.Bar()

Definition

Src/a/Foo.ts

export module mylib {
    export class Foo {
    }
}

SRC/B/Bar.ts

export module mylib {
    export class Bar {
    }
}

Src/index.ts

import { Foo } from './a/Foo'
import { Bar } from './b/Bar'

export { Foo, Bar }

Testing

测试/a/Foo.spec.ts

import { mylib } from "../src";

test("constructor"), () = {
   const foo = new mylib.Foo() // expectation
}

测试/b/Bar.spec.ts

test("constructor"), () = {
   const bar = new mylib.Bar() // expectation
}

推荐答案

假设您只想要您所询问的最终结果,而不是专门try 使用TypeScrip的module语法,那么您可以简化一点,然后有几个选项.

简单地说,您不需要Foo.tsBar.ts中的export module mylib { /* ... */ }个包装器,只需要:

export class Foo
    // ...
}

export class Bar
    // ...
}

然后,问题就变成了你希望如何从index.ts个国家进口这些产品.

模块命名空间对象

What you have now in index.ts is actually just fine for one way it could be used: It creates two named exports, FooBar. If you want to write code using those via a mylib object, you can create that on import:

import * as mylib from "../src";
//     ^^^^^^^^^^

That import syntax says "Import the module namespace object for the module 和 assign it to a binding called mylib." If the module namespace object doesn't already exist for that module, it'll be created.

进口后的用法如问题mylib.Foo等所示.

But doing it that way, it's also possible to use import { Foo } from "../src"; 和/or import { Bar } from "../src";. Normally that's a good thing, but if you don't want to allow that, you won't want to do individual named exports.

Note that import * as mylib will defeat tree-shaking, if that's important to what you're doing. (Which is part of why import { Foo } 和 such are normally a good thing.) But it's the person using your library who makes that decision; your library doesn't prevent tree-shaking by itself.

导出对象

如果您不想采用上面的模块命名空间对象方法,可以从index.ts中导出一个对象:

export const mylib = { Foo, Bar };

...或可能将其冻结导出,以便无法添加、删除或重新分配属性:

export const mylib = Object.freeze({ Foo, Bar });

那么导入就像您在问题中所展示的那样:

import { mylib } from "../src";

使用量为mylib.Foo等.

Beware that this defeats tree-shaking, 和 not just based on how users use it, but at the library level (by not having FooBar exports people could use instead). I wouldn't recommend it.

两者都有

Finally, you could support both named individual exports 和 a single named object export. In that case, the exports in index.ts would look like this:

export { Foo, Bar };
export const mylib = Object.freeze({Foo, Bar});

如果您这样做了,您就让使用代码的人来决定是使用import { Foo }还是import { mylib }.这保持了库对树摇动的友好性,同时还为整个库提供了命名导出(如果有用的话).

Typescript相关问答推荐

Typescript如何从字符串中提取多个文本

如何用不同的键值初始化角react 形式

类型脚本接口索引签名

将值添加到具有不同类型的对象的元素

为什么我的Set-Cookie在我执行下一次请求后被擦除

如何在TypeScript中将一个元组映射(转换)到另一个元组?

如何在TypeScrip中正确键入元素和事件目标?

通过字符串索引访问对象';S的值时出现文字脚本错误

被推断为原始类型的交集的扩充类型的交集

在对象中将缺省值设置为空值

从对象类型描述生成类型

Angular:ngx-echart 5.2.2与Angular 9集成错误:NG 8002:无法绑定到选项,因为它不是div的已知属性'

有没有一种方法可以确保类型的成员实际存在于TypeScript中的对象中?

刷新时保持当前名称的Angular

递归生成常量树形 struct 的键控类型

为什么TS条件返回要求不明确的强制转换而不是精确的强制转换?

递归JSON类型脚本不接受 node 值中的变量

将对象数组传递给 Typescript 中的导入函数

剧作家测试未加载本地网址

如何使用 TypeScript 接口中第一个属性的值定义第二个属性