cloudflare / workerd

The JavaScript / Wasm runtime that powers Cloudflare Workers

Home Page:https://blog.cloudflare.com/workerd-open-source-workers-runtime/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Standard `WebSocket` type returned instead of type from `@cloudflare/workers-types`

missinglink opened this issue · comments

Version

"@cloudflare/workers-types": "4.20240222.0"

Expected

deserializeAttachment() exists on WebSocket type returned by DurableState.getWebSockets()

Screenshot 2024-03-07 at 11 43 29

Actual

DurableState.getWebSockets() returns type globalThis.WebSocket (standard type as defined by MDN Reference):

Screenshot 2024-03-07 at 11 39 50

Suggestion

The types file does in fact include a type for the Cloudflare implementation of WebSocket which includes this signature, but this is not the Type which is returned.

Screenshot 2024-03-07 at 11 40 16

Anecdote

Could this be due to the WebSocket type definition coming later in the types file than the DurableObjectState definition?

Workaround:

declare module '@cloudflare/workers-types/experimental' {
  export interface DurableObjectState extends OriginalDurableObjectState {
    acceptWebSocket: (ws: WebSocket, tags?: string[]) => void
    getWebSockets: (tag?: string) => WebSocket[]
    getWebSocketAutoResponseTimestamp: (ws: WebSocket) => Date | null
    getTags: (ws: WebSocket) => string[]
  }
  export declare const WebSocketPair: {
    new (): {
      0: WebSocket
      1: WebSocket
    }
  }
}

I ran into this as well. I don't think it's actually a cloudflare issue though. The issue (at least for me) was that lib.dom.d.ts (which has the conflicting definition of WebSocket) was being inadvertently added to my project[1]. Even if it's not included in your tsconfig, if you have any dependencies that reference it, it gets pulled in globally (see microsoft/TypeScript#43990 and microsoft/TypeScript#37053)

[1] It was being added via fetch-retry package (which incidentally just fixed their types to stop doing that: jonbern/fetch-retry#88).

@russelldavis I still believe it's a CloudFlare issue as the second screenshot from within CloudFlare type definitions file shows a modal which lists the return type as globalThis.WebSocket.

I will investigate what you said and report back.

CloudFlare type definitions file shows a modal which lists the return type as globalThis.WebSocket

That's correct and expected. The Cloudflare library defines WebSocket as a global definition (because it is available without importing, per standards). Everything works properly as long as you don't import a library with a conflicting global WebSocket definition.

I ran into this issue a couple months ago when a package in my project was using the WebSocket type from lib.dom.d.ts, the solution for me was to add the following declaration extending the WebSocket type with the @cloudflare/workers-types WebSocket type.

import { type WebSocket as CloudflareWebSocket } from '@cloudflare/workers-types'

declare global {
	interface WebSocket extends CloudflareWebSocket {}
  }