2026-08-24
Using JSDOM with Deno and TypeScript
Sometimes you need to parse HTML in Deno and query it with familiar DOM APIs
such as querySelectorAll().
JSDOM works well for this, but there is one
TypeScript gotcha: its types live in the separate @types/jsdom package.
Install JSDOM and its types
deno add jsdom @types/jsdomThen import it like this:
// @ts-types="@types/jsdom"
import { JSDOM } from "jsdom";The @ts-types directive tells Deno which declarations belong to the jsdom
import. This is especially useful when your project is not using a local
node_modules directory (i.e. when using Deno).
Example
// @ts-types="@types/jsdom"
import { JSDOM } from "jsdom";
const res = await fetch("https://example.com");
const html = await res.text();
const dom = new JSDOM(html);
const document = dom.window.document;
const rows = document.querySelectorAll<HTMLTableRowElement>(
".searchlistgreyrow, .searchlistwhiterow",
);
for (const row of rows) {
console.log(row.innerHTML);
}JSDOM gives you a window and document, so APIs such as querySelector(),
textContent, and innerHTML work much like they do in the browser.
The generic on querySelectorAll() is useful here:
document.querySelectorAll<HTMLTableRowElement>("tr");A CSS selector does not tell TypeScript which HTML element it matches. Supplying
HTMLTableRowElement gives each result the correct type, including properties
such as cells and rowIndex.
That's it: install jsdom and its types, connect them with @ts-types, and you
get a familiar DOM API with proper TypeScript checking in Deno.