Here is how I handle communication over Electron channels:
preload.ts
contextBridge.exposeInMainWorld("myIpcRenderer", {
invoke: (channel: Channel, ...args: any[]) =>
callIpcRenderer("invoke", channel, ...args),
send: (channel: Channel, ...args: any[]) =>
callIpcRenderer("send", channel, ...args),
on: (channel: Channel, ...args: any[]) =>
callIpcRenderer("on", channel, ...args),
});
types.d.ts
interface MyIpcRenderer {
invoke(channel: Channel.ReadFiles, ...args: any[]): Promise<ReadFileResult[]>;
}
The MyIpcRenderer
type enforce correct use in renderer.ts
:
const files = await window.myIpcRenderer.invoke(Channel.ReadFiles, [
svgPath,
]);
But it does not enforce correct use in main.ts
. ipcMain.handle
refers to an electron method that can accept channels with any name and retturn any kind of promise.
ipcMain.handle(
"anychannelnamegoes",
async (_event, paths: string[]): Promise<any> => {
...
}
);
How can I rewrite my code to enforce main usage in main.ts
as well?
I see two ways to do this.
First possibility is to override Electron library types declaration in your typings.d.ts
file:
declare module 'electron' {
export interface IpcMain extends NodeJS.EventEmitter {
handle(
channel: Channel,
listener: (
event: IpcMainInvokeEvent,
...args: any[]
) => Promise<void> | any
): void;
}
}
Considering that Channel
is a string literal (type Channel = 'channel1' | 'channel2'
), you would get suggestions for 'channel1'
and 'channel2'
, but the initial signature channel: string
would still be allowed and any string would be accepted.
The second possibility I see is to wrap it, which would give better type safety:
const myHandler = (
channel: Channel,
listener: (
event: IpcMainInvokeEvent,
...args: any[]
) => Promise<void> | any
) => ipcMain.handle(channel, listener);
// only 'channel1' and 'channel2' would be accepted
myHandler('channel1', (event) => {});
I you would like to type the arguments currently declared with the spread operator ...args: any[]
you would need to declare the parameters explicitly in both cases:
...
listener: (
event: IpcMainInvokeEvent,
arg1: string[],
arg2: boolean,
arg3: number
) => Promise<void> | any
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With