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 Element | TypeScript Type | Key Properties |
|---|---|---|
<input> | HTMLInputElement | value, type, placeholder, checked |
<button> | HTMLButtonElement | disabled, textContent, type |
<select> | HTMLSelectElement | value, selectedIndex, options |
<textarea> | HTMLTextAreaElement | value, rows, cols |
<form> | HTMLFormElement | reset(), submit(), elements |
<img> | HTMLImageElement | src, alt, width, height |
<a> | HTMLAnchorElement | href, target, rel |
<ul>, <ol> | HTMLUListElement, HTMLOListElement | children, appendChild() |
<div> | HTMLDivElement | innerHTML, 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);
