Tumgik
#I realized the involvement of advanced concepts like type assertion and union types. I now understand why the authors of those tutorials di
learn-from-my-experience ยท 8 months
Text
Every TypeScript example and tutorial I've come across so far mainly focuses on language features, static typing, and working with Visual Studio. However, I couldn't find much guidance on how to use TypeScript effectively with JavaScript and the DOM.
I remember having the same question a while back, just like Johnny on Stack Overflow. "Can we use TypeScript to manipulate the DOM?" This question motivated me to dive deeper and figure it out, and I'm here to share what I've learned.
Configuration: Using TypeScript for DOM manipulation is straightforward, but it does require some configuration. You'll need to include the specific types for DOM access, which aren't available by default in TypeScript. To do this, you must explicitly configure the TypeScript compiler to include the "dom" library in the compilerOptions section of your tsconfig.json file. It's worth noting that the decision not to include these types by default might suggest that TypeScript's creators initially intended it more for server-side development with Node.js than for front-end work.
/** tsconfig.json - Configuration file in the project folder for the TypeScript compiler */ { "compilerOptions": { "lib": [ "es2015", "dom" ], "strict": true, "target": "es2015" } }
Hello World: In this article, I'll create a simple "Hello, world!" program to demonstrate how to use the DOM in TypeScript. Since this is my first post about TypeScript, I'll cover the basics of working with DOM types and address a common challenge that beginners might encounter. Please note that I won't be discussing DOM events in this post; that's a topic for a future article.
Let's start with the basics by changing the inner text value of an existing HTML element. I began by creating an HTML file with a standard HTML5 boilerplate, including an <h1> element with the id "greeter" in the body.
<!DOCTYPE html> <html lang="en"> <head> <!-- ... --> </head> <body> <h1 id="greeter">Hello</h1> </body> </html>
Next, I opened a new TypeScript file and added the following code:
let greeter: HTMLHeadingElement = document.getElementById("greeter") as HTMLHeadingElement; greeter.innerText = "Hello world!";
Tumblr media
In this code, I created a variable called greeter and assigned the type HTMLHeadingElement to it. The HTMLHeadingElement type is defined in the "dom" library we added to the configuration. It tells the TypeScript compiler that greeter expects an HTML heading element and nothing else. Then, I assigned the greeter to the value returned by the getElementById function, which selects an element by its ID. Finally, I set the inner text of the greeter element to "Hello world."
When I compiled the code with the following command:
tsc script.ts
Tumblr media
It produced the following error:
Type 'HTMLElement | null' is not assignable to type 'HTMLHeadingElement'. Type 'null' is not assignable to type 'HTMLHeadingElement'.
It's a bit frustrating, but TypeScript is doing its job. This error means that I tried to assign a greeter, which is of type HTMLHeadingElement, with an object of type HTMLElement that the getElementById method returned. The HTMLElement | null in the error message indicates that the method's return value can be either of type HTMLElement or null.
To address this, I used TypeScript's type assertion feature to tell the compiler that the element returned by getElementById is indeed a heading element, and it doesn't need to worry about it. Here's the updated code:
let greeter: HTMLHeadingElement = document.getElementById("greeter") as HTMLHeadingElement; greeter.innerText = "Hello world!";
Tumblr media
With this change, the compilation was successful. I included the script.js file generated by the compiler in the HTML document and opened it in a browser.
Tumblr media
Decoration Time: Now that I've confirmed that everything works as intended, it's time to make the page more visually appealing. I wanted a font style that was informal, so I chose the "Rock Salt" font from Google Fonts. I imported it into my stylesheet, along with "Dancing Script" as a secondary font, using CSS imports. I then added a few more elements to the HTML document, centered all the text using CSS flexbox, added a background from UI gradients, and adjusted the positions of some elements for proper arrangement. The page now looked beautiful.
Animation: To add a finishing touch, I wanted to include a background animation of orbs rising to the top like bubbles. To create the orbs, I decided to use <div> elements. Since I wanted several orbs with different sizes, I split the task into two steps to simplify the work.
First, I created a common style for all the orbs and defined a custom animation for the orbs in CSS. Then, I created the orbs dynamically using TypeScript. I created a set number of <div> elements, assigned them the pre-defined style, and randomized their sizes, positions, and animation delays to make them appear more natural.
Here's an excerpt of the code for creating the bubbles:
function createBubbles() { for (let i = 0; i < bubbleCount; i++) { let div: HTMLDivElement = document.createElement("div") as HTMLDivElement; let divSize = getSize(); div.style.left = getLeftPosition() + "px"; div.style.width = divSize + "px"; div.style.height = divSize + "px"; div.style.animationDelay = i * randomFloat(0, 30) + "s"; div.style.filter = "blur(" + randomFloat(2, 5) + "px)"; div.classList.add("bubble"); bubbleBuffer.push(div); } console.log("Bubbles created"); }
After creating the orbs, I added them to the DOM and started the animation:
function releaseBubbles() { createBubbles(); for (let i = 0; i < bubbleCount; i++) { containerDiv.appendChild(bubbleBuffer[i]); } console.log("Bubbles released"); }
And with that, the animation of orbs rising like bubbles was set in motion.
Here's the final output:
youtube
You can find the complete code in this repository.
Conclusion: While writing this article and creating the example, I realized the involvement of advanced concepts like type assertion and union types. I now understand why the authors of those tutorials didn't include them; introducing them could confuse beginners. It's best to learn TypeScript thoroughly before venturing into DOM manipulation.
In my example, I skipped null checking when fixing the type mismatch error, as it seemed unnecessary for the demonstration. However, in real projects, it's important to check for null values to avoid runtime errors. I also didn't
0 notes