socket-controllers
socket-controllers copied to clipboard
feature: Make typings in decorators from socket Server: ListenEvents, EmitEvents...
Description
I am migrating to socket-controllers from an existing socket.io installation, which is using typings for messages, parameters, and socket data (I don't use ServerEvents yet).
This looks like this:
type ClientToServerEvents = {
joinGame: (gameId: string, answer: (joined: true | string) => void) => void;
};
type ServerToClientEvents = {
gameCreated: (hostedGameData: HostedGameData) => void;
}
interface SocketData {
player: null | PlayerData;
}
const io = new Server<ClientToServerEvents, ServerToClientEvents, DefaultEventsMap, SocketData> {}
Then it allows to have type checks for message names, parameters:
socket.on('joinGame', (gameId, answer) => { ... }); // 'joinGame' is checked and typo are impossible, gameId and answer types are infered
// There is also typechecks for this:
socket.data.player; // type PlayerData is infered
When migrating to socket-controllers, I have not found how to retrieve that, for example:
@OnMessage('...'): Should typecheck"joinGame"@MessageAck() ack: Type should be(joined: true | string) => void- parameter decorator (havn't tested yet, just starting with socket-controllers)
I could find a workaround for the first case by doing something like:
import { OnMessage as BaseOnMessage } from 'socket-controllers';
export function OnMessage(name: keyof ClientToServerEvents) {
return BaseOnMessage(name);
}
But it is trickier for @MessageAck() !
Proposed solution
Not sure at all, but when we do:
const io = new Server<ClientToServerEvents, ServerToClientEvents, DefaultEventsMap, SocketData> {}
new SocketControllers({
io,
controllers: [
...,
],
});
Probably there is a way to retrieve all Server types and put them to decorators, or maybe add generics to new SocketControllers<ListenEvents, EmitEvents, ...>() same as when doing new Server<...>().
The advantage of creating the server that you use to define all events is that you can carry the type information. Since with socket-controllers you define your own controllers separately, it is not possible to carry that type information as far as I know.
The workaround you found only works if you define the decorator yourself. In our case, it must be a generic but then you lose access to the inferred type and you would have to define the type again in every instance of that decorator in the controllers.
If you think this is achievable and you have a solution please let me know, I would be glad to accept a PR for this.