ws: Cannot augment WebSocket interface in TypeScript

when adding a method sendAsync to WebSocket, i have to augment the interface of WebSocket

// promisify.ts
export function promisifySend(socket: WebSocket): void {
    socket.sendAsync = function (/*......*/): Promise<void> {
        /*......*/
    }
}
declare module 'ws' {
    export default interface Websocket { // default export
        sendAsync(/*......*/): Promise<void>;
    }
}

//1.ts
import WebSocket from 'ws'; // import a default export
import { promisifySend } from './promisify.ts';

but this syntax above is illegal in TS, see https://github.com/microsoft/TypeScript/issues/14080

TS only allows to augment a interface which is a named export, for example

// promisify.ts
export function promisifySend(socket: WebSocket): void {
    socket.sendAsync = function (/*......*/): Promise<void> {
        /*......*/
    }
}
declare module 'ws' {
    export interface Websocket { // named export
        sendAsync(/*......*/): Promise<void>;
    }
}

// 1.ts
import { WebSocket } from 'ws'; // import a named export
import { promisifySend } from './promisify.ts';

this requires WebSocket is not default export but a named export.

obviously, this is a bug of TS, not of ws. but you cannot look forward to TS fixing its bug. so i recommend ws exports a WebSocket within WebSocket, like

// index.js
const WebSocket = require('./lib/websocket');
WebSocket.WebSocket = WebSocket;
module.exports = WebSocket;

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 23 (9 by maintainers)

Commits related to this issue

Most upvoted comments

This isn’t just a typescript change this would also make intellisense better for standard js users

It is. What the OP requested can easily be done with no changes with CJS and it has nothing to do with intellisense. There is no WebSocket property on the WebSocket object and in my opinion it does not make sense to add it only to work around some TypeScript limitations.

Why exactly are you so against this? There’s no downside apart from having to “support” typescript (that’s being generous).

It creates a property on the WebSocket object that does not make sense. I don’t like that.

We don’t ship nor maintain TypeScript type definitions. Please open this issue in the DefinitelyTyped repository.

I don’t see why personal opinion should have any relevance here. This would help developers. This wouldn’t add any extra work for you. Why are you holding us back? This doesn’t make any sense.

Adding that property now is easy. Removing it, if/when the issue is fixed in TypeScript, would be a breaking change… just like WebSocket.createWebSocketStream, WebSocket.Server, WebSocket.Receiver, and WebSocket.Sender. They should not exist.

Maybe this is worth taking a vote with contributors of this repo?

Sure. cc: @websockets/core @websockets/contributors

No thanks, again, I don’t want changes only required for TypeScript.

Is there a reason for this? This isn’t just a typescript change this would also make intellisense better for standard js users.

Maybe this is worth taking a vote with contributors of this repo?

Is there some logical reasoning for not wanting to change this or is this simply hate towards Typescript?

No thanks, again, I don’t want changes only required for TypeScript.