I'm creating a browser extension and in order to communicate between background and frontend I need to use chrome.runtime.sendMessage()
In my frontend script, I want to send a message to the background, so I do this:
chrome.runtime.sendMessage({ action: 'setUpdate', value: { total: 4, alarm: false } })
And in the background I receive it like this:
chrome.runtime.onMessage.addListener((message: BackgroundMessage) => {
switch (message.action) {
case 'setUpdate':
...
break;
}
});
My problem is creating the BackgroundMessage
type, as each action
will have a different value type.
I've tried this:
interface actions {
setUpdate: { total: number; alarm: boolean };
setReminder: { text: string; when: Date };
}
type BackgroundMessage = Record<keyof actions, actions>;
But I don't know how to specify that the keys of the action interface need to be in the action
property, and the value types in the value
property.
Is this possible?
CodePudding user response:
You already have defined a map of actions to values, so you could use a mapped type to make a discriminated union from that map:
interface Actions {
setUpdate: { total: number; alarm: boolean };
setReminder: { text: string; when: Date };
}
type BackgroundMessage = {
[K in keyof Actions]: { action: K; value: Actions[K] };
}[keyof Actions];
Then you can narrow the type based on the action:
if (msg.action === "setReminder") {
msg.value.text // ok
}