Repository navigation
adapter-cloudflare: the runtime types from wrangler types merge with lib.dom's Element, so HTMLSelectElement is no longer assignable to HTMLElement #17372
Description
Describe the bug
The adapter docs say to run wrangler types so that platform can be typed, and the sv template puts the generated worker-configuration.d.ts in compilerOptions.types. That file declares the HTMLRewriter API as global interfaces, among them:
interface Element {
tagName: string;
// ...
remove(): Element;
// ...
}$app/tsconfig sets lib: ["esnext", "DOM", "DOM.Iterable"], so this declaration merges with lib.dom's Element. lib.dom's HTMLSelectElement overrides remove as remove(index?: number): void; after the merge, Element.remove also has the (): Element signature, and the override no longer satisfies it:
Type 'HTMLSelectElement' is not assignable to type 'HTMLElement'.
The types returned by 'remove()' are incompatible between these types.
Type 'void' is not assignable to type 'Element'.
In practice: any bind:this from a <select> into an HTMLElement | null fails svelte-check. shadcn-svelte's native-select does exactly that, so sv create with the Cloudflare adapter plus shadcn-svelte add native-select does not pass pnpm check.
Cloudflare treats the overlap as intended. In cloudflare/workers-sdk#10108 a maintainer wrote that "Cloudflare Workers types are intentionally designed to be used independently from DOM types, not alongside them" and closed the issue. The setup the adapter docs and the sv template produce is that combination, which is why I am filing this here rather than there.
Reproduction
No SvelteKit needed; the clash is between lib.dom and the generated file:
mkdir repro && cd repro && npm init -y && npm i -D typescript wrangler
echo '{ "name": "repro", "main": "worker.js", "compatibility_date": "2026-10-05" }' > wrangler.jsonc
npx wrangler types
echo 'const el: HTMLElement = document.createElement("select");' > repro.ts
npx tsc --noEmit --strict --lib es2022,dom --skipLibCheck repro.ts worker-configuration.d.tsThe same tsc call without worker-configuration.d.ts passes.
In a SvelteKit project:
npx sv@1.1.0 create --template minimal --types ts --add sveltekit-adapter="adapter:cloudflare+cfTarget:workers" --install npm repro
cd repro && npx wrangler types
cat > src/lib/Select.svelte <<'SVELTE'
<script lang="ts">
let ref: HTMLElement | null = $state(null);
</script>
<select bind:this={ref}></select>
SVELTE
npm run checkLogs
Error: Type 'HTMLSelectElement' is not assignable to type 'HTMLElement'.
The types returned by 'remove()' are incompatible between these types.
Type 'void' is not assignable to type 'Element'. (ts)
<select
bind:value
bind:this={ref}
Same result with TypeScript 5.9 and 6.0.3.
System Info
System:
OS: Linux 7.0 Ubuntu 26.04.1 LTS
Binaries:
Node: 24.21.0
npm: 11.19.0
pnpm: 11.10.0
npmPackages:
@sveltejs/adapter-cloudflare: ^8.0.0 => 8.0.0
@sveltejs/kit: ^3.0.0 => 3.0.0
@sveltejs/vite-plugin-svelte: ^7.2.0 => 7.3.1
svelte: ^5.57.1 => 5.57.1
svelte-check: ^4.6.0 => 4.7.6
typescript: ^6.0.3 => 6.0.3
vite: ^8.3.0 => 8.3.2
wrangler: ^4.97.0 => 4.147.0 (runtime types from workerd 1.20261001.1)
Severity
serious, but I can work around it
Additional Information
wrangler types --include-runtime=false emits only the Env interface, which has no DOM overlap, but then Fetcher, ExecutionContext and IncomingRequestCfProperties are undefined and App.Platform cannot be typed the way the docs show. If the adapter shipped those few types itself, projects could generate Env only and keep lib.dom intact. Failing that, a note in the adapter docs that the runtime types and bind:this on form elements do not mix would save the next person the afternoon.
Activity
svelte-triage-bot commentedon Oct 7, 2026
I reproduced the issue, but could not produce a safe, verified fix.
What I tried
wrangler typesmerge with lib.dom'sElement, soHTMLSelectElementis no longer assignable toHTMLElement#17372 and its comments through the GitHub connection: The issue is open with no comments or closing PR. It confirms that Wrangler's global HTMLRewriter Element merges with lib.dom and changes HTMLSelectElement assignability.npx tsc --noEmit --strict --lib es2022,dom --skipLibCheck repro.ts worker-configuration.d.tsfailed with TS2322: HTMLSelectElement.remove(): void is incompatible with Element.remove(): Element. Omitting the generated declarations passed.npx sv@1.1.0 createCloudflare Workers setup, generated types, added Select.svelte, and rannpm run check: The generated project failed exactly at<select bind:this={ref}>with the reported HTMLSelectElement-to-HTMLElement diagnostic.npm run check: Current source still failed with the identical diagnostic, confirming this is not already fixed in the checkout.wrangler typesmerge with lib.dom'sElement, soHTMLSelectElementis no longer assignable toHTMLElement#17372 or the DOM collision. PR feat:@cloudflare/vite-pluginintegration, take 2 #16705 is a broader Cloudflare Vite plugin draft and does not isolate runtime declarations.skipLibCheckcannot stop declaration merging from changing user-code assignability.wrangler types --include-runtime=falseand selectiveimport('@cloudflare/workers-types').Typedeclarations: Runtime-disabled generation avoids the DOM collision. A generated app excluding the full runtime file and selectively typingcloudflare:workersplus Request.cf passed svelte-check, including both the select binding and a typed env.ASSETS.fetch call.wrangler typesin cloudflare adapter #16808, fix cloudflare docs types #16810, breaking: Move cloudflare bindings fromplatformtocloudflare:workers#16754, and fix: avoid colliding with user-typedplatform.env#16043 and recorded /workspace/notes.md: The current Wrangler strategy intentionally replaced incomplete manual types to preserve generated binding/runtime accuracy; Kit 3 also moved APIs from App.Platform to cloudflare:workers. The failing sv template configuration lives in the separate sveltejs/cli repository.Why I stopped
The bug is reproducible, but a safe fix is not practical within this Kit checkout. The root cause is combining two ambient libraries that Cloudflare intentionally does not support together. Symptom patches such as augmenting Element.remove or relying on skipLibCheck leave many other Request, Headers, Response, stream, cache, WebSocket, and HTMLRewriter collisions.
--include-runtime=falseis safe for DOM types, but its generated Env references a large and changing set of Worker globals; preserving useful, compatibility-date-aware typing requires Cloudflare to provide an isolated/importable generated type surface, or requires a coordinated redesign of adapter typing and the sveltejs/cli template (which owns the reported generated tsconfig/App.Platform setup). Reverting Kit docs to hand-maintained selective bindings would be incomplete, while shipping a static alias list would drift from Wrangler configurations. No unverified patch was committed or pushed.