3

我一起使用 TypeScript 和 SignalR,并尝试为生成的 SignalR 类定义静态类型。如果我做这样的事情,它会起作用:

///<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 { }
}

当然$.connection是类型SignalR,它在文件“signalr-1.0.d.ts”中定义,并在上面的文件中扩展。

但是,我需要能够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 { }
}

但是,当我这样做时,我在 下得到一条红色的波浪线$.connection.roomHub,编译器返回错误“SignalR 类型上不存在属性 'roomHub'。”

我当然不了解有关 TypeScript 的所有内容,但这对我来说似乎不正确。我遇到了编译器错误吗?还是有其他方法可以做到这一点?

4

3 回答 3

6

我能够想出一个解决方法。我将接口提取到一个单独的文件中:

// File: ISignalR.ts
interface SignalR {
    roomHub: RoomHub;
}

interface RoomHub {
}

然后我在我的服务文件中引用了该文件

///<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;
}

这很有效,很奇怪。我不确定这是编译器错误,还是我继续误解的东西,但它显然与一些与 AMD 模块支持相关的细微语义变化有关。我很想听听比我更了解 TypeScript 和/或 RequireJS 模块的人的更多解释。

于 2012-11-26T22:39:27.467 回答
2

连接 SignalR 的方法不止一种,并且使用createHubProxyinvokeTypeScript 更友好:

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);
                }
            });
        });
    }
}

这是一个从真实代码中截取的稍微粗略的示例,但我发现它是使用 SignalR 的最佳 TS 方式。这种连接的文档在这里:https ://github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs-%28No-Proxy%29 - 请注意,因为文档并不总是跟上最近的变化。

于 2012-11-27T11:47:00.600 回答
2

如果SignalR对象有实际成员,您想改用declare module语法。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 { }
}
于 2012-11-26T22:02:44.220 回答