Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions types/ws/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ declare class WebSocket extends EventEmitter {
onclose: (event: WebSocket.CloseEvent) => void;
onmessage: (event: WebSocket.MessageEvent) => void;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
constructor(address: null);

constructor(address: null);
constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
constructor(
address: string | URL,
Expand Down Expand Up @@ -291,6 +292,7 @@ declare namespace WebSocket {
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
maxPayload?: number | undefined;
skipUTF8Validation?: boolean | undefined;
WebSocket?: typeof WebSocket.WebSocket | undefined;
}

interface AddressInfo {
Expand All @@ -300,10 +302,10 @@ declare namespace WebSocket {
}

// WebSocket Server
class Server extends EventEmitter {
class Server<T extends WebSocket = WebSocket> extends EventEmitter {
options: ServerOptions;
path: string;
clients: Set<WebSocket>;
clients: Set<T>;

constructor(options?: ServerOptions, callback?: () => void);

Expand All @@ -313,36 +315,36 @@ declare namespace WebSocket {
request: IncomingMessage,
socket: Duplex,
upgradeHead: Buffer,
callback: (client: WebSocket, request: IncomingMessage) => void,
callback: (client: T, request: IncomingMessage) => void,
): void;
shouldHandle(request: IncomingMessage): boolean | Promise<boolean>;

// Events
on(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
on(event: "error", cb: (this: Server, error: Error) => void): this;
on(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
on(event: "close" | "listening", cb: (this: Server) => void): this;
on(event: string | symbol, listener: (this: Server, ...args: any[]) => void): this;

once(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
once(event: "error", cb: (this: Server, error: Error) => void): this;
once(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
once(event: "close" | "listening", cb: (this: Server) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;

off(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
off(event: "error", cb: (this: Server, error: Error) => void): this;
off(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
off(event: "close" | "listening", cb: (this: Server) => void): this;
off(event: string | symbol, listener: (this: Server, ...args: any[]) => void): this;

addListener(event: "connection", cb: (client: WebSocket, request: IncomingMessage) => void): this;
on(event: "connection", cb: (this: Server<T>, socket: T, request: IncomingMessage) => void): this;
on(event: "error", cb: (this: Server<T>, error: Error) => void): this;
on(event: "headers", cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void): this;
on(event: "close" | "listening", cb: (this: Server<T>) => void): this;
on(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;

once(event: "connection", cb: (this: Server<T>, socket: T, request: IncomingMessage) => void): this;
once(event: "error", cb: (this: Server<T>, error: Error) => void): this;
once(event: "headers", cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void): this;
once(event: "close" | "listening", cb: (this: Server<T>) => void): this;
once(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;

off(event: "connection", cb: (this: Server<T>, socket: T, request: IncomingMessage) => void): this;
off(event: "error", cb: (this: Server<T>, error: Error) => void): this;
off(event: "headers", cb: (this: Server<T>, headers: string[], request: IncomingMessage) => void): this;
off(event: "close" | "listening", cb: (this: Server<T>) => void): this;
off(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;

addListener(event: "connection", cb: (client: T, request: IncomingMessage) => void): this;
addListener(event: "error", cb: (err: Error) => void): this;
addListener(event: "headers", cb: (headers: string[], request: IncomingMessage) => void): this;
addListener(event: "close" | "listening", cb: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;

removeListener(event: "connection", cb: (client: WebSocket) => void): this;
removeListener(event: "connection", cb: (client: T) => void): this;
removeListener(event: "error", cb: (err: Error) => void): this;
removeListener(event: "headers", cb: (headers: string[], request: IncomingMessage) => void): this;
removeListener(event: "close" | "listening", cb: () => void): this;
Expand Down
32 changes: 32 additions & 0 deletions types/ws/ws-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,35 @@ declare module 'ws' {
skipUTF8Validation: true,
});
}

{
class CustomWebSocket extends WebSocket.WebSocket {
foo(): 'foo' {
return 'foo';
}
}
const server = new http.Server();
const webSocketServer = new WebSocket.WebSocketServer<CustomWebSocket>({WebSocket: CustomWebSocket, noServer: true});
webSocketServer.on('connection', (ws) => {
// $ExpectType CustomWebSocket
ws;
// $ExpectType "foo"
ws.foo();
});
Copy link
Copy Markdown
Contributor

@vansergen vansergen Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
});
});
webSocketServer.clients.forEach((ws) => {
// $ExpectType CustomWebSocket
ws;
// $ExpectType "foo"
ws.foo();
});

Array.from(webSocketServer.clients).forEach((ws) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for future reference:

ERROR: 332:1   expect                     TypeScript@4.6: Can not match a node to this assertion.
ERROR: 334:1   expect                     TypeScript@4.6: Can not match a node to this assertion.

// $ExpectType CustomWebSocket
ws;
// $ExpectType "foo"
ws.foo();
});
server.on('upgrade', (request, socket, head) => {
if (request.url === '/path') {
webSocketServer.handleUpgrade(request, socket, head, (ws) => {
// $ExpectType CustomWebSocket
ws;
// $ExpectType "foo"
ws.foo();
});
}
});
}