我有一个包含大量模块的文件。我想将这些模块分离到不同的文件中,并从原始文件中公开它们。这是因为原始文件是>800 loc,并且变得非常难以管理。
所以我创建了一个包含函数和接口的模块的文件:
export module Subsection1 {
export interface Interface {
id: string;
}
export function DoInterfaceStuff(obj: any) {
return = <Interface>{ id: obj }
}
}
我有
import { Subsection1 as Subsection1Base } from "./Subsection1";
export module GodManager {
export type Subsection1 = Subsection1Base & (typeof Subsection1Base);
export var Subsection1 = Subsection1Base;
var ObjByID = new Map<string, Subsection1.Interface>();
export function DoThing(source) {
ObjByID.set(source.id, Subsection1.DoInterfaceStuff(source.origin));
}
}
注意新名称和变量必须可以被当前类外部访问,因为我实际上是惰性加载Subsection1Base(主要是为了避免循环依赖)。
@Connor Low的答案通过强调正确的错误为我指明了正确的方向,但这是问题的实际解决方案。
从这个github问题中导入的模块可以使用import export Name = Value
语法重新导出。
import { Subsection1 as Subsection1Base } from "./Subsection1";
export module GodManager {
export import Subsection1 = Subsection1Base;
var ObjByID = new Map<string, Subsection1.Interface>();
export function DoThing(source) {
ObjByID.set(source.id, Subsection1.DoInterfaceStuff(source.origin));
}
}
这一切都行得通!
序曲
问题改变了示例代码,但他们最初导出了具有相同名称的module
和interface
,并试图在只有interface
有效的上下文中引用module
。虽然在不同语言结构的两个不同声明之间共享一个名称不一定是不正确的,但它确实模糊了他们正在经历的真正问题(参见下面的原始答案)。
原始回答
如果我们清理类型的命名,我们可以很快地找出这里的问题。
在TriggerEvent中,我们将接口Trigger
重命名为ITrigger
:
export interface ITrigger {
// ..
}
export module Trigger {
//...
export function Serialise(restoredEvent: ITrigger) {
//...
}
}
现在,在ActionManager
中,我们可以看到哪里出错了:
import { Trigger as TriggerBase } from "./TriggerEvent";
export module ActionManager {
type Trigger = TriggerBase & (typeof Trigger);
// ^^^^^^^^^^^
// ERROR - Cannot use namespace 'TriggerBase' as a type.
var Trigger = TriggerBase;
var EventsByID = new Map<UUID, Trigger>();
var PrepreparedInputs = new Map<UUID, Trigger.Serialised>();
// ^^^^^^^
// ERROR - 'Trigger' only refers to a type, but is being used as a namespace here.
}
不能使用命名空间(模块)作为类型。(见文档)。在此之前,由于接口和模块的命名是相同的,TypeScript使用了与上下文相适应的选项——接口。因此,没有错误!无论如何,我们仍然有原来的错误'Trigger' only refers to a type...
,因为类型是类型,而不是名称空间(或模块)。
最后,ActionManager.Trigger.Serialise(stuff);
不工作,因为触发器没有从ActionManager模块导出。
解决方案由于您不能将module
分配给type
,请直接在PreparedInputs
中引用该模块:
var PrepreparedInputs = new Map<UUID, TriggerBase.Serialised>();
并且,正如您对TriggerEvent
所做的那样,导出您想要在模块外部使用的类型/变量:
// The interface was renamed to ITrigger in TriggerEvent.
import { Trigger as TriggerBase, ITrigger } from "./TriggerEvent";
export module ActionManager {
export var Trigger = TriggerBase;
export var EventsByID = new Map<UUID, ITrigger>();
export var PrepreparedInputs = new Map<UUID, TriggerBase.Serialised>();
}