Reputation: 20445
I'm using TypeScript and SignalR together, and am trying to define static types for the generated SignalR classes. 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.
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, i.e.:
///<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."
I certainly don't understand everything about TypeScript, but that doesn't seem right to me. Have I run into a compiler bug? Or is there a different way to do this?
Upvotes: 3
Views: 3045
Reputation: 20445
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. I'd love to hear more of an explanation from someone who groks TypeScript and/or RequireJS modules a little better than I do.
Upvotes: 6
Reputation: 11294
There is more than one way to wire SignalR up, and using createHubProxy
and invoke
are more TypeScript friendly:
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. 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.
Upvotes: 2
Reputation: 221154
If the SignalR
object has actual members, you want to use the declare module
syntax instead. interface
declarations only describe members on types (rather than describing extant objects).
///<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 { }
}
Upvotes: 2