Skip to content

Commit 8b93a18

Browse files
authored
fix(sio): allow emitWithAck() for events with void callbacks (#5453)
EventNamesWithAck previously excluded events whose callback had no non-error arguments (e.g. `(cb: () => void) => void` or `(cb: (err: Error) => void) => void`). This made it impossible to use emitWithAck as a simple acknowledgement mechanism without data. The fix removes the FirstNonErrorArg void check while keeping the guard against events with no parameters at all, so events like `() => void` (no callback) are still correctly excluded. Related: #5257
1 parent e6c722e commit 8b93a18

2 files changed

Lines changed: 14 additions & 17 deletions

File tree

packages/socket.io/lib/typed-events.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ export type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
2222

2323
/**
2424
* Returns a union type containing all the keys of an event map that have an acknowledgement callback.
25-
*
26-
* That also have *some* data coming in.
2725
*/
2826
export type EventNamesWithAck<
2927
Map extends EventsMap,
@@ -32,11 +30,11 @@ export type EventNamesWithAck<
3230
Last<Parameters<Map[K]>> | Map[K],
3331
K,
3432
K extends (
35-
Last<Parameters<Map[K]>> extends (...args: any[]) => any
36-
? FirstNonErrorArg<Last<Parameters<Map[K]>>> extends void
37-
? never
38-
: K
39-
: never
33+
Parameters<Map[K]> extends never[]
34+
? never
35+
: Last<Parameters<Map[K]>> extends (...args: any[]) => any
36+
? K
37+
: never
4038
)
4139
? K
4240
: never

packages/socket.io/test/socket.io.test-d.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,11 @@ describe("server", () => {
265265
interface ServerToClientEventsWithMultipleWithAck {
266266
ackFromServer: (a: boolean, b: string) => Promise<boolean[]>;
267267
ackFromServerSingleArg: (a: boolean, b: string) => Promise<string[]>;
268-
// This should technically be `undefined[]`, but this doesn't work currently *only* with emitWithAck
269-
// you can use an empty callback with emit, but not emitWithAck
270268
onlyCallback: () => Promise<undefined>;
271269
}
272270
interface ServerToClientEventsWithAck {
273271
ackFromServer: (a: boolean, b: string) => Promise<boolean>;
274272
ackFromServerSingleArg: (a: boolean, b: string) => Promise<string>;
275-
// This doesn't work currently *only* with emitWithAck
276-
// you can use an empty callback with emit, but not emitWithAck
277273
onlyCallback: () => Promise<undefined>;
278274
}
279275
describe("Emitting Types", () => {
@@ -420,8 +416,9 @@ describe("server", () => {
420416
sio.timeout(0).emitWithAck("noArgs");
421417
// @ts-expect-error - "helloFromServer" doesn't have a callback and is thus excluded
422418
sio.timeout(0).emitWithAck("helloFromServer");
423-
// @ts-expect-error - "onlyCallback" doesn't have a callback and is thus excluded
424-
sio.timeout(0).emitWithAck("onlyCallback");
419+
expectType<
420+
ToEmitWithAck<ServerToClientEventsWithMultipleWithAck, "onlyCallback">
421+
>(sio.timeout(0).emitWithAck<"onlyCallback">);
425422
expectType<
426423
ToEmitWithAck<
427424
ServerToClientEventsWithMultipleWithAck,
@@ -496,10 +493,12 @@ describe("server", () => {
496493
s.emitWithAck("noArgs");
497494
// @ts-expect-error - "helloFromServer" doesn't have a callback and is thus excluded
498495
s.emitWithAck("helloFromServer");
499-
// @ts-expect-error - "onlyCallback" doesn't have a callback and is thus excluded
500-
s.emitWithAck("onlyCallback");
501-
// @ts-expect-error - "onlyCallback" doesn't have a callback and is thus excluded
502-
s.timeout(0).emitWithAck("onlyCallback");
496+
expectType<
497+
ToEmitWithAck<ServerToClientEventsWithAck, "onlyCallback">
498+
>(s.emitWithAck<"onlyCallback">);
499+
expectType<
500+
ToEmitWithAck<ServerToClientEventsWithAck, "onlyCallback">
501+
>(s.timeout(0).emitWithAck<"onlyCallback">);
503502
expectType<
504503
ToEmitWithAck<ServerToClientEventsWithAck, "ackFromServerSingleArg">
505504
>(s.emitWithAck<"ackFromServerSingleArg">);

0 commit comments

Comments
 (0)