Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Make typings in decorators from socket Server: ListenEvents, EmitEvents... #888

Open
alcalyn opened this issue Feb 23, 2024 · 1 comment
Labels
flag: needs discussion Issues which needs discussion before implementation. type: feature Issues related to new features.

Comments

@alcalyn
Copy link

alcalyn commented Feb 23, 2024

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<...>().

@alcalyn alcalyn added flag: needs discussion Issues which needs discussion before implementation. type: feature Issues related to new features. labels Feb 23, 2024
@attilaorosz
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flag: needs discussion Issues which needs discussion before implementation. type: feature Issues related to new features.
Development

No branches or pull requests

2 participants