My goal is to establish an abstract relationship between different sub-types of Message
and Response
, allowing for a generic function that takes a Message
as input and returns a corresponding Response
. Specifically, when the function is called with type MessageTypeA
, I want the response type to always be ResponseTypeA
, and I need TypeScript to enforce this connection in some way.
Here's a depiction of the issue using TypeScript:
type MessageTypeA = { a: string };
type MessageTypeB = { b: number };
type MessageTypeC = [number, number];
type Message = MessageTypeA | MessageTypeB | MessageTypeC;
type ResponseTypeA = { a: boolean; aa: number };
type ResponseTypeB = "hello" | "bye";
type ResponseTypeC = number;
type Reponse = ResponseTypeA | ResponseTypeB | ResponseTypeC;
type Pair<M extends Message, R extends Reponse> = {
message: M;
response: R;
};
// Ideally should use a Map/Record instead
type ValidPairsMap =
| Pair<MessageTypeA, ResponseTypeA>
| Pair<MessageTypeB, ResponseTypeB>
| Pair<MessageTypeC, ResponseTypeC>;
// A rough implementation attempt:
function sendMessageReturnResponse<T extends ValidPair>(
message: typeof T.message
): typeof T.response {
throw "uncertain how to accomplish this";
}
function main() {
let mesA: MessageTypeA = { a: "msg" };
let resA: ResponseTypeA = sendMessageReturnResponse(mesA);
// error: return value of sendMessageReturnResponse cannot be inferred to be ResponseTypeA
}
In light of this challenge, what steps can I take to achieve the intended outcome?