首页 > 解决方案 > OpenTok 事件 Typescript 输入

问题描述

我试图通过OpenTok API使用“信号”事件来发布/订阅来实现聊天。

这是我的事件监听器(接收到信号):

// Listen for signal CHAT_MESSAGE
sess.on('signal:CHAT_MESSAGE', event => {
 
  const message = event.data

  ...

}) 

问题是打字稿不能识别event.data为有效属性。类型来自 Session 类:

Session.signal: Event<'signal', Session> & {
    type?: string;
    data?: string;
    from: Connection;
};

我尝试从 Session 类中选择类型,例如

const message = event.data as Session['signal']

打字稿抱怨Property 'data' does not exist on type 'Event<string, any>'.我怀疑这是因为 TS 无法正确识别事件类型......

然后我尝试先转换为“未知”:

const signal = (event as unknown) as Session['signal']
const msg = signal.data

现在 TS 抱怨:Property 'data' does not exist on type '(signal: { type?: string | undefined; data?: string | undefined; to?: Connection | undefined; }, callback: (error?: OTError | undefined) => void) => void'.ts(2339)

我不知道为什么它不认为这data是一个道具,同时它似乎说它是......

如何解决这个问题,最好不禁用 TS 类型检查?

标签: typescriptopentok

解决方案


问题是Session['signal']一个函数:

signal(
    signal: { type?: string, data?: string, to?: Connection },
    callback: (error?: OTError) => void
): void;

您可能需要的类型来自Session的类祖先OTEventEmitter

export class Session extends OTEventEmitter<{
    ...
    signal: Event<'signal', Session> & {
      type?: string;
      data?: string;
      from: Connection;
    };
    ...

OTEventEmitter.on方法类型:

class OTEventEmitter<EventMap> {
    on<EventName extends keyof EventMap>(
        eventName: EventName,
        callback: (event: EventMap[EventName]) => void,
        context?: object
    ): void;

    on(
        eventName: string,
        callback: (event: Event<string, any>) => void,
        context?: object
    ): void;
    ...

正如您可能会注意到,当Session扩展OTEventEmittersignal:CHAT_MESSAGEEventMap. 只有signal.

因此,如果您希望您signal:CHAT_MESSAGE被视为一个signal事件,您应该将其写为:

sess.on('signal:CHAT_MESSAGE' as 'signal', event => {
    const message = event.data // no error
    // `event` has type
    // Event<'signal', Session> & {
    //     type?: string;
    //     data?: string;
    //     from: Connection;
    // }
    ...

这种类型转换没有运行时伪影。唯一的目的是确保您的事件与'ssignal:CHAT_MESSAGE具有相同的结构。signal尽管现在与as关键字一样,但您有责任确保这一点成为现实。


推荐阅读