一段时间以来,我一直在搜索和阅读相关信息,但是仍然无法解决这个问题。
当我使用打字稿创建库或包时,我喜欢将declaration
设置为true,以便ts编译器编译源代码时,它将自动为我生成声明文件。典型的库或程序包通常具有一个入口文件和一堆相互依赖的文件。因此,构建结果的输出将如下所示:
.
├── build
| ├── entry.js (or entry.min.js in production)
| ├── entry.d.ts (it depends on moduleA)
| ├── moduleA.d.ts (it depends on moduleB)
| ├── moduleB.d.ts
| ├── types.d.ts (contains shared types for every body)
| └── util.d.ts (declarations for some random util functions)
在package.json
中,我将设置为:
{
...
"main": "./build/entry.js",
"types": "./build/entry.d.ts",
...
}
问题是,即使entry.js
具有我要向消费者公开的所有API,entry.d.ts
也没有我也要公开的所有类型。这是因为即使entry.ts
中有import
个types.ts
,类型声明也不会自动从中导入。消费者可能想使用我保存在types.ts
(因此types.d.ts
)中的一些枚举,而不是entry.ts
(因此entry.d.ts
)中的枚举。
使用这些类型的一种方法是将其重新导出到条目文件中,例如:
export * from './types';
// or
export { EnumA } from './types';
这将允许消费者这样做:
import * as types from 'mylib';
// or
import { EnumA } from 'mylib';
这是我现在正在做的事情,它更多是一个手动工作流程,很可能我忘记导出消费者实际上需要使用我的库的某些类型。我可以将所有类型/接口/枚举放在一个types.ts
文件中,然后导出所有内容,但是我不确定这是否正确。
typescript团队正在使用名称空间来处理此问题(例如server types和service types),但是IMO是多余的,因为我们已经在使用ES6模块。有关更多信息,请参见great cup example for explaining namespaces with modules。
另一种解决方法是让消费者这样做
import * as types from 'mylib/build/types'
但是IMO这也是一种不好的做法,因为我们实际上向用户公开了实现细节,我们将来可能会更改它。
我还要补充一点,如果我想为具有commonjs或AMD结构的ES5代码生成库,则typescript offical document表示要使用export =
。显然,这将阻止您再使用export * from './types'
,因此上述解决方法将不再起作用。
这就是我现在的位置。有什么建议么?现在,我倾向于像打字稿团队一样使用名称空间,但我想听听更多的想法。