TypeScript DOM Manipulation

The Document Object Model (DOM) represents the HTML structure of a webpage as a tree of objects. TypeScript provides built-in type definitions for every DOM element and event, making DOM manipulation safe, error-free, and editor-assisted. TypeScript knows exactly what properties and methods each HTML element supports — so typos and incorrect method calls get caught before the browser runs the code.

How TypeScript Knows DOM Types

  HTML Document
  +-----------------------------------+
  | <html>                           |
  |   <body>                         |
  |     <h1 id="title">...</h1>      |  ← HTMLHeadingElement
  |     <input id="name" />          |  ← HTMLInputElement
  |     <button id="submit">...</button> | ← HTMLButtonElement
  |     <ul id="list">...</ul>       |  ← HTMLUListElement
  |   </body>                        |
  +-----------------------------------+

  TypeScript has type definitions for ALL HTML elements
  in the built-in "lib.dom.d.ts" file (no install needed).

Selecting Elements

The document.getElementById() method returns HTMLElement | null because the element might not exist. TypeScript enforces handling both possibilities.

// TypeScript infers: HTMLElement | null
let title = document.getElementById("title");

// Must check for null before using
if (title !== null) {
    title.textContent = "Welcome to eStudy247";
}

// Shorter null check using optional chaining
document.getElementById("title")?.remove();

Type Assertion for Specific Elements

When the specific element type is known (input, button, etc.), assert the type to access element-specific properties like value on inputs.

// Without assertion — only HTMLElement properties available
let nameInput = document.getElementById("name");
nameInput.value; // Error: 'value' does not exist on 'HTMLElement'

// With assertion — full HTMLInputElement properties available
let nameInput = document.getElementById("name") as HTMLInputElement;
nameInput.value;       // Valid ✓
nameInput.placeholder; // Valid ✓
nameInput.disabled;    // Valid ✓

querySelector and querySelectorAll

// querySelector — returns first matching element or null
let submitBtn = document.querySelector<HTMLButtonElement>("#submit");
submitBtn?.click();

// querySelectorAll — returns NodeList of all matching elements
let listItems = document.querySelectorAll<HTMLLIElement>("li.course-item");

listItems.forEach(item => {
    item.style.color = "blue";
    console.log(item.textContent);
});

Common DOM Element Types

HTML ElementTypeScript TypeKey Properties
<input>HTMLInputElementvalue, type, placeholder, checked
<button>HTMLButtonElementdisabled, textContent, type
<select>HTMLSelectElementvalue, selectedIndex, options
<textarea>HTMLTextAreaElementvalue, rows, cols
<form>HTMLFormElementreset(), submit(), elements
<img>HTMLImageElementsrc, alt, width, height
<a>HTMLAnchorElementhref, target, rel
<ul>, <ol>HTMLUListElement, HTMLOListElementchildren, appendChild()
<div>HTMLDivElementinnerHTML, className, style

Event Listeners

TypeScript knows the exact event type for each event name. The callback receives a correctly typed event object with all its properties available.

let button = document.getElementById("submit") as HTMLButtonElement;

// TypeScript infers event as MouseEvent
button.addEventListener("click", (event: MouseEvent) => {
    console.log("Clicked at X: " + event.clientX + ", Y: " + event.clientY);
    event.preventDefault(); // Available on MouseEvent
});

let input = document.getElementById("name") as HTMLInputElement;

// TypeScript infers event as Event (generic input event)
input.addEventListener("input", (event: Event) => {
    let target = event.target as HTMLInputElement;
    console.log("Typed: " + target.value);
});

// Keyboard event
input.addEventListener("keydown", (event: KeyboardEvent) => {
    if (event.key === "Enter") {
        console.log("Enter pressed with value: " + input.value);
    }
});

Creating and Appending Elements

// Create a new list item and add it to a list
let courseList = document.getElementById("course-list") as HTMLUListElement;

function addCourse(courseName: string): void {
    let li = document.createElement("li");  // HTMLLIElement
    li.textContent = courseName;
    li.className = "course-item";
    courseList.appendChild(li);
}

addCourse("TypeScript Mastery");
addCourse("React Fundamentals");
addCourse("Node.js Backend");

Modifying Styles

let card = document.getElementById("course-card") as HTMLDivElement;

// Inline styles
card.style.backgroundColor = "#f0f4ff";
card.style.padding          = "16px";
card.style.borderRadius     = "8px";

// CSS classes
card.classList.add("active");
card.classList.remove("loading");
card.classList.toggle("highlighted");

console.log(card.classList.contains("active")); // true

Form Handling

interface CourseFormData {
    title: string;
    instructor: string;
    level: string;
    price: number;
}

function handleFormSubmit(event: SubmitEvent): CourseFormData {
    event.preventDefault();

    let titleInput     = document.getElementById("title") as HTMLInputElement;
    let instructorInput = document.getElementById("instructor") as HTMLInputElement;
    let levelSelect    = document.getElementById("level") as HTMLSelectElement;
    let priceInput     = document.getElementById("price") as HTMLInputElement;

    return {
        title:      titleInput.value.trim(),
        instructor: instructorInput.value.trim(),
        level:      levelSelect.value,
        price:      parseFloat(priceInput.value)
    };
}

let form = document.getElementById("course-form") as HTMLFormElement;
form.addEventListener("submit", (event: SubmitEvent) => {
    let data = handleFormSubmit(event);
    console.log("Course submitted:", data);
});

Practical Example — Dynamic Course List

interface Course {
    id: number;
    title: string;
    instructor: string;
    price: number;
}

const courses: Course[] = [
    { id: 1, title: "TypeScript Mastery",    instructor: "Anand Rao",  price: 999 },
    { id: 2, title: "React Fundamentals",    instructor: "Priya Nair", price: 799 },
    { id: 3, title: "Node.js Backend",       instructor: "Suresh M",   price: 1099 }
];

function renderCourses(list: Course[]): void {
    let container = document.getElementById("courses") as HTMLDivElement;
    container.innerHTML = "";

    list.forEach((course: Course) => {
        let card = document.createElement("div");
        card.className = "course-card";
        card.innerHTML = `
            <h3>${course.title}</h3>
            <p>Instructor: ${course.instructor}</p>
            <p>Price: ₹${course.price}</p>
        `;

        let enrollBtn = document.createElement("button");
        enrollBtn.textContent = "Enroll Now";
        enrollBtn.addEventListener("click", () => {
            console.log("Enrolled in: " + course.title);
        });

        card.appendChild(enrollBtn);
        container.appendChild(card);
    });
}

// Search filter
let searchInput = document.getElementById("search") as HTMLInputElement;
searchInput.addEventListener("input", (e: Event) => {
    let term = (e.target as HTMLInputElement).value.toLowerCase();
    let filtered = courses.filter(c => c.title.toLowerCase().includes(term));
    renderCourses(filtered);
});

renderCourses(courses);

Leave a Comment