'Typing events on the server and client
I have some third party framework with functionality to add an event listener on the server and call that event from the client side.
That look like this for server:
framework.addEvent('myEvent1', (clientId, myParam1, myParam2...) => { my server work here })
And on client side:
let result = await framework.callRemote('myEvent1', myParam1, myParam2,...)
I do not understand how to correctly and conveniently describe the types of my events, their string names and associated callback types that I could use on the server and client sides (by importing these types from the global module).
Each callback on the server side always has a clientId as first argument, but next my parameters and their types may be different for each event.
I only came up this:
export namespace ServerEvent {
export enum Name {
MyEvent1 = 'MyEvent1',
MyEvent2 = 'MyEvent2',
MyEvent3 = 'MyEvent3',
}
export namespace Func {
export type MyEvent1 = (myArg1: string) => void
export type MyEvent2 = (myArg1: number, myArg2?: boolean) => void
export type MyEvent3 = () => void
}
}
But even this I don't understand how to use it to see all arguments and their types on server and client side.
I found some example of which perhaps solves my problem, but I cannot grasp it and how to move in this direction:
const wrapper = <U extends (...args: any[]) => any>(func: U) => (...args: Parameters<U>) : ReturnType<U> => func(...args);
Solution 1:[1]
I found some solution, I suspect not the best, but I almost achieved my goal:
// GLOBAL Module
export enum ServerEventName {
Event1 = 'MyEvent1',
Event2 = 'MyEvent2',
Event3 = 'MyEvent3',
Event4 = 'MyEvent4', // events can be withot callback type if they has no other arguments besides clientId
}
export namespace ServerCallback {
export type Event1Callback = (arg1: string) => void
export type Event2Callback = (arg1: number, arg2?: boolean) => void
export type Event3Callback = () => void
}
// SERVER
function addEvent<U extends (...args: any[]) => any>(name: string, callback: (clientId: number, ...args: Parameters<U>) => ReturnType<U>) {
someFramework.addEvent(name, (clientId: number, ...args: Parameters<U>) => { callback(clientId, ...args) })
}
addEvent<ServerCallback.Event1Callback>(ServerEventName.Event1, (clientId, arg1) => {
console.log(clientId, arg1)
})
addEvent<ServerCallback.Event2Callback>(ServerEventName.Event2, (clientId, arg1, arg2) => {
console.log(clientId, arg1, arg2)
})
addEvent<ServerCallback.Event3Callback>(ServerEventName.Event3, (clientId) => {
console.log(clientId)
})
// CLIENT
function callRemoteEvent<U extends (...args: any[]) => any>(name: string, ...args: Parameters<U>) {
someFramework.callRemote(name, ...args)
}
callRemoteEvent<ServerCallback.Event1Callback>(ServerEventName.Event1, 'this is string')
callRemoteEvent<ServerCallback.Event2Callback>(ServerEventName.Event2, 123, true)
callRemoteEvent<ServerCallback.Event3Callback>(ServerEventName.Event3)
callRemoteEvent(ServerEventName.Event4)
IDE syntax helpers successfully recognize types and inspect them.
However, there are some drawbacks. Events name enum are not related to theyr callback types, and need to indicate them correctly together.
UPD: this This answer completely solves my question.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |