You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
Currently functions like emit are not typable:
socket.emit('my-event-name', dto);
This applies to both socket.io server and client.
Describe the solution you'd like
I would like to have generic types on all emit functions to (optionally) type the send-object and the response-object:
I have a WIP implementation that would fix this issue on this branch. @darrachequesne would there be interest in potentially merging something like that? If so, I can complete the implementation.
The implementation adds two optional type parameters to Socket, Server and Namespace. These type parameter are a mapping of event names to listener types; by default, it's a mapping of all strings to (...args: any[]) => void, so it retains the current behavior if no type parameters are passed. However, users can optionally pass a mapping of their event names to the types of the listeners that listen to those events.
But this solution is not perfect; their implementation has a thing called assignmentCompatibilityHack, which sometimes fails in weird ways. So I think that in order to properly address this issue, we need to implement some stricter event typing in socket.io.
You could always cast the socket to a Socket<A, B> with the exact A or B event maps you need for each function call.
But as far as I know, most type-safe event-emitter libraries actually take the same approach as what I implemented, i.e. an interface declaring all events and their types ahead of time.
Activity
MaximeKjaer commentedon Feb 26, 2021
I have a WIP implementation that would fix this issue on this branch. @darrachequesne would there be interest in potentially merging something like that? If so, I can complete the implementation.
The implementation adds two optional type parameters to
Socket,ServerandNamespace. These type parameter are a mapping of event names to listener types; by default, it's a mapping of allstrings to(...args: any[]) => void, so it retains the current behavior if no type parameters are passed. However, users can optionally pass a mapping of their event names to the types of the listeners that listen to those events.MaximeKjaer commentedon Feb 26, 2021
@MickL in the meantime, this library may be of interest to you: https://github.com/bterlson/strict-event-emitter-types (also see the blog post that explains the library). It allows you to cast socket.io types as strictly typed
EventEmitter. The README has an example of this in action.But this solution is not perfect; their implementation has a thing called
assignmentCompatibilityHack, which sometimes fails in weird ways. So I think that in order to properly address this issue, we need to implement some stricter event typing in socket.io.darrachequesne commentedon Feb 26, 2021
@MaximeKjaer as long as the feature is stable and does not fail in surprising ways during compilation, that sounds interesting 😄
feat: add support for typed events (#3822)
feat: add support for typed events
darrachequesne commentedon Mar 11, 2021
This was implemented by 0107510 (server) and socketio/socket.io-client@5902365 (client) and included in Socket.IO v4 🔥
Syntax:
Documentation: https://socket.io/docs/v3/migrating-from-3-x-to-4-0/#Typed-events
MickL commentedon Mar 11, 2021
Not exactly what I desired but it should work. I wanted to do it per function instead of per server.
darrachequesne commentedon Mar 11, 2021
@MickL if you want to only type certain events, you should be able to do:
MickL commentedon Mar 11, 2021
I meant more like this
socket.emit<void, MyDtoInterface>('my-event-name', dto);Thats how most other libraries do it.
MaximeKjaer commentedon Mar 11, 2021
You could always cast the
socketto aSocket<A, B>with the exactAorBevent maps you need for each function call.But as far as I know, most type-safe event-emitter libraries actually take the same approach as what I implemented, i.e. an interface declaring all events and their types ahead of time.
MickL commentedon Mar 11, 2021
For example Angular http client does it like this:
https://github.com/angular/angular/blob/2c757591ee334ced115bc93ba1b944803bb0c07e/packages/common/http/src/client.ts#L2291
Or all NestJS Microservice Clients:
https://github.com/nestjs/nest/blob/eb239abd8261b3328945865790ffc3c377b60827/packages/microservices/client/client-proxy.ts#L60
I specifically used NestJS as the source of my proposal above.
It is easy to implement two generics, it does not add any extra code and is totally optional to use.
feat: add support for typed events
feat: add support for typed events (socketio#3822)