[英]Exporting a TypeScript module results in interfaces not getting picked up
I'm using TypeScript and SignalR together, and am trying to define static types for the generated SignalR classes. 我一起使用TypeScript和SignalR,并且我正在尝试为生成的SignalR类定义静态类型。 And if I do something like this, it works: 如果我做这样的事情,它的工作原理:
///<reference path="../Scripts/jquery-1.8.d.ts" />
///<reference path="../Scripts/signalr-1.0.d.ts" />
interface SignalR {
roomHub: Service.RoomHub;
}
module Service {
export var roomHub = $.connection.roomHub;
export interface RoomHub { }
}
And of course $.connection
is of type SignalR
, which is defined in the file "signalr-1.0.d.ts", and extended in the file above. 当然$.connection
SignalR
是SignalR
类型,它在文件“signalr-1.0.d.ts”中定义,并在上面的文件中扩展。
However, I need to be able to reference the Service
module from other files, so I need to add the "export" keywords to both the module and the interface, ie: 但是,我需要能够从其他文件引用Service
模块,所以我需要在模块和接口上添加“export”关键字,即:
///<reference path="../Scripts/jquery-1.8.d.ts" />
///<reference path="../Scripts/signalr-1.0.d.ts" />
export interface SignalR {
roomHub: Service.RoomHub;
}
export module Service {
// Error here: "The property 'roomHub' does not exist on type SignalR."
export var roomHub = $.connection.roomHub;
export interface RoomHub { }
}
However, when I do that, I get a little red squiggly line under $.connection.roomHub
, and the compiler returns the error, "The property 'roomHub' does not exist on type SignalR." 但是,当我这样做时,我在$.connection.roomHub
下得到一条红色的小红线,并且编译器返回错误,“属性'RoomHub'在SignalR类型上不存在。”
I certainly don't understand everything about TypeScript, but that doesn't seem right to me. 我当然不了解TypeScript的所有内容,但这对我来说似乎并不合适。 Have I run into a compiler bug? 我遇到了编译器错误吗? Or is there a different way to do this? 或者有不同的方法来做到这一点?
I was able to figure out a workaround. 我找到了一个解决方法。 I pulled out the interfaces into a separate file: 我将接口拉出到一个单独的文件中:
// File: ISignalR.ts
interface SignalR {
roomHub: RoomHub;
}
interface RoomHub {
}
And then I referenced that file in my Service file 然后我在我的服务文件中引用了该文件
///<reference path="../Scripts/jquery-1.8.d.ts" />
///<reference path="../Scripts/signalr-1.0.d.ts" />
///<reference path="ISignalR.ts" />
export module Service {
export var roomHub = $.connection.roomHub;
}
And that works, oddly enough. 这很有效,奇怪的是。 I'm not sure if it's a compiler bug, or something I'm continuing to misunderstand, but it clearly has something to do with some subtle semantic changes related to the AMD module support. 我不确定这是一个编译器错误,还是我继续误解的东西,但它显然与一些与AMD模块支持相关的细微语义变化有关。 I'd love to hear more of an explanation from someone who groks TypeScript and/or RequireJS modules a little better than I do. 我很想听到更多来自那些比我更好地理解TypeScript和/或RequireJS模块的人的解释。
If the SignalR
object has actual members, you want to use the declare module
syntax instead. 如果SignalR
对象具有实际成员,则需要使用declare module
语法。 interface
declarations only describe members on types (rather than describing extant objects). interface
声明仅描述类型上的成员(而不是描述现有对象)。
///<reference path="../Scripts/jquery-1.8.d.ts" />
///<reference path="../Scripts/signalr-1.0.d.ts" />
declare module SignalR {
var roomHub: Service.RoomHub;
}
export module Service {
// Good now
export var roomHub = $.connection.roomHub;
export interface RoomHub { }
}
There is more than one way to wire SignalR up, and using createHubProxy
and invoke
are more TypeScript friendly: 连接SignalR的方法不止一种,使用createHubProxy
和invoke
更适合TypeScript:
export class FrameworkHub {
private connection: HubConnection;
private proxy: HubProxy;
Init(): void {
this.Connected = false;
this.connection = $.hubConnection();
this.connection.logging = true;
// Binding with createHubProxy means you can use a string name, so no need to add dynamic properties to the hub
this.proxy = this.connection.createHubProxy("MyHubName");
this.wireEventListeners();
this.initializeConnection();
}
// Binding with proxy.on means you can use a string name for the function, so no need to add dynamic properties to the hub.
wireEventListeners(): void {
this.proxy.on("HandleFrameworkMessage", (message: IFrameworkMessage) => {
console.log("HandleFrameworkMessage: " + message.AccountID + " - " + message.ArmID);
// Do something to handle the message here.
});
}
initializeConnection(): void {
//console.log("Framework Hub initializeConnection");
var that = this;
//Again, using invoke means passing a string argument.
this.connection.start().done(() => {
that.proxy.invoke("Connect", this.AccountID, this.ArmID).done((response:FrameworkHubResponse) => {
//console.log("FHR: " + response.Success + " - " + response.Message);
if (response.Success) {
// Do something.
}
else {
// Try again. Would be better with some kind of exponential back-off.
setTimeout(that.initializeConnection, 500);
}
});
});
}
}
That's a slightly rough example cut from real code, but I've found it the best TS way to use SignalR. 这是一个从实际代码中略微粗略的例子,但我发现它是使用SignalR的最佳TS方式。 Docs for this kind of connection are here: https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs-%28No-Proxy%29 - watch out because the Docs haven't always kept pace with the recent changes. 这种连接的文档在这里: https : //github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs-%28No-Proxy%29 - 小心,因为文档并不总是跟上最近的变化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.