将消息类型与有效负载类型相关联

时间:2019-03-14 16:03:13

标签: typescript

我正在尝试创建消息总线API,该消息中的消息只能与特定类型/形状的有效载荷一起发送。

我基本上是在这样做,以便当我开始键入对emitMessage的调用(如下)时,我希望IDE能够为{{1}提供编译时类型提示。 }参数一旦指定了payload,就可以知道任何给定消息类型期望使用哪种type

我已经尝试过以下操作:

payload

但是该代码不完整/不正确,因为我不知道如何指定// I create some generic payload interface that can be any shape interface Payload<T> { [key: string]: any } // I define an enum of permitted message types enum MessageType { TEST } // And then I expose a function for emitting messages of a particular type // along with its associated payload function emitMessage<Msg extends MessageType>(type: Msg, payload: Payload<Msg>) { // ... } 枚举的特定变体与MessageType的特定专业化相关。

我不确定这是否可能,因此,对此方向的任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

我发现了this script形式的非常酷的解决方案

// I define an enum of permitted message types
enum MessageType {
    TEST
}

// This interface is then used as a kind of "type directory"
interface Payload {
    [MessageType.TEST]: {
        test: boolean
    }
}

// payload's type here is now an index into the Payload type directory
function emitMessage<M extends MessageType>(msg: M, payload: Payload[M]) {
    switch(msg) {
        case MessageType.TEST: {
            // payload.test is suggested by my IDE now! 
        }
    }
}

此功能很棒,我想将其用于所有功能

答案 1 :(得分:0)

一种方法是使用有区别的联合。首先在您的有效负载中添加一个字段,以指示其类型,例如kind beliow

interface Square {
    kind: "square";
    size: number;
}
interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}
interface Circle {
    kind: "circle";
    radius: number;
}

首先,我们声明要合并的接口。每个接口都有一个具有不同字符串文字类型的kind属性。 kind属性称为判别式或标记。其他属性特定于每个接口。请注意,接口当前不相关。让我们将它们组成一个联合体:

type Shape = Square | Rectangle | Circle;

现在让我们使用有区别的联合:

function area(s: Shape) {
  switch (s.kind) {
      case "square": return s.size * s.size;
      case "rectangle": return s.height * s.width;
      case "circle": return Math.PI * s.radius ** 2;
  }
}

请参见Advanced Types