The deltic host module is browser-first JS, but it does not type-check in a compilation that includes the dom lib — which is exactly the configuration of a consumer's browser-facing module graph. Found while porting polymorph-iroh's upstream-iroh experiments onto deltic (polymorph-components/polymorph-iroh#41): the experiments' browser entries need dom for document etc., deno check type-checks local imports (the .deps sibling checkouts included), and adding dom to the shared config broke the graph on this module — so those browser entries now sit outside the type-check gate, with the bundle + Playwright suites carrying them instead (noted in that PR's experiments/iroh-relay-ws/host/deno.json comment).
Repro
Against current main (6632473) or the polymorph-iroh pin (2000f54), with the module's own js/deltic/deno.json plus one compilerOptions addition:
$ deno check --config that.json js/deltic/websocket.ts
TS2345 [ERROR]: Argument of type 'string | Uint8Array<ArrayBufferLike>' is not assignable to parameter of type 'string | BufferSource | Blob'.
Type 'Uint8Array<ArrayBufferLike>' is not assignable to type 'ArrayBufferView<ArrayBuffer>'.
this.#ws.send(message.val as string | Uint8Array);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at js/deltic/websocket.ts:460:21
One error; the rest of the file is clean under dom. Deno 2.9.5 / TypeScript 6.0.3.
Why it only shows up downstream
- TypeScript's generic typed arrays (5.7+): bare
Uint8Array means Uint8Array<ArrayBufferLike>, i.e. "possibly SharedArrayBuffer-backed".
- The
dom lib's WebSocket.send(data: string | BufferSource | Blob) excludes SAB-backed views (BufferSource = ArrayBufferView<ArrayBuffer> | ArrayBuffer), tracking the platform rule that shared buffers don't cross these APIs.
- Deno's own
WebSocket.send declaration is more permissive, so the repo's deno task check (default lib, no dom) stays green.
Suggested fix
The cast at the send site is the whole problem; tightening it is sound here: binary payloads reaching send are either lifted by the deltic embedder (list<u8> → always a fresh copy, per its value-mapping contract) or supplied by host-side callers, and a SAB-backed view would be refused by the platform API at runtime anyway — typing it away is strictly more honest:
this.#ws.send(message.val as string | Uint8Array<ArrayBuffer>);
(Alternative, if you'd rather push the constraint to the public surface: type Message's binary case as Uint8Array<ArrayBuffer> — but that ripples into every consumer's Message literals, so the local cast seems proportionate.)
Worth adding dom to a check lane (or a second deno check task with a dom-lib config) so the browser-consumer configuration is covered by the gate that this repo owns, rather than each consumer rediscovering it.
The deltic host module is browser-first JS, but it does not type-check in a compilation that includes the
domlib — which is exactly the configuration of a consumer's browser-facing module graph. Found while porting polymorph-iroh's upstream-iroh experiments onto deltic (polymorph-components/polymorph-iroh#41): the experiments' browser entries needdomfordocumentetc.,deno checktype-checks local imports (the.depssibling checkouts included), and addingdomto the shared config broke the graph on this module — so those browser entries now sit outside the type-check gate, with the bundle + Playwright suites carrying them instead (noted in that PR'sexperiments/iroh-relay-ws/host/deno.jsoncomment).Repro
Against current main (
6632473) or the polymorph-iroh pin (2000f54), with the module's ownjs/deltic/deno.jsonplus onecompilerOptionsaddition:{ "imports": { "@deltic/runtime/embedder": "…as in js/deltic/deno.json…" }, "compilerOptions": { "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"] } }One error; the rest of the file is clean under
dom. Deno 2.9.5 / TypeScript 6.0.3.Why it only shows up downstream
Uint8ArraymeansUint8Array<ArrayBufferLike>, i.e. "possibly SharedArrayBuffer-backed".domlib'sWebSocket.send(data: string | BufferSource | Blob)excludes SAB-backed views (BufferSource=ArrayBufferView<ArrayBuffer> | ArrayBuffer), tracking the platform rule that shared buffers don't cross these APIs.WebSocket.senddeclaration is more permissive, so the repo'sdeno task check(default lib, nodom) stays green.Suggested fix
The cast at the send site is the whole problem; tightening it is sound here: binary payloads reaching
sendare either lifted by the deltic embedder (list<u8>→ always a fresh copy, per its value-mapping contract) or supplied by host-side callers, and a SAB-backed view would be refused by the platform API at runtime anyway — typing it away is strictly more honest:(Alternative, if you'd rather push the constraint to the public surface: type
Message's binary case asUint8Array<ArrayBuffer>— but that ripples into every consumer'sMessageliterals, so the local cast seems proportionate.)Worth adding
domto a check lane (or a seconddeno checktask with a dom-lib config) so the browser-consumer configuration is covered by the gate that this repo owns, rather than each consumer rediscovering it.