Description
Describe the bug
When using socket.timeout.emitWithAck
, even if you set EmitEvents
correctly, the return type will be a wrong any
.
To Reproduce
no need for server participation.
Server
Socket.IO client version: 4.7.4
Client
import type { Socket } from 'socket.io-client'
type MySocket = Socket<DefaultEventsMap, EmitEvents>
type DefaultEventsMap = {
[event: string]: (...args: any[]) => void
}
type EmitEvents = {
hello: (cb: (val: number) => void) => void
}
const socket = {} as MySocket
const r1 = socket.emitWithAck('hello') // Promise<number>
const r2 = socket.timeout(1000).emitWithAck('hello') // Promise<any>
Expected behavior
r2
should also be inferred as Promise<number>
.
Platform:
- Typescript version:
5.3.3
Additional context
The return type of emitWithAck
is from Promise<FirstArg<Last<EventParams<EmitEvents, Ev>>>>
, which picks the first argument of cb
. However, timeout
uses DecorateAcknowledgements
then PrependTimeoutError
, which prepend a Error
type param to cb
, so this FirstArg
will focus on the error instead of the real return value.
Maybe replace FirstArg
with a type LastArg<T> = T extends (...args: infer Args) => any ? Args extends [] ? never : Args extends [...infer _, infer Last] ? Last : never : never;
will solve this issue? I'm not so familiar with the js logic, so just a hypothesis.
By the way, I have found the same problem in #4813 , it can be solved by using socket options ackTimeout
in the client side (I have already adopted this solution). But I think it's better if this problem can be solved completely.