Learning TypeScript: Hello world with DOM manipulation
Vijay Koushik, S. šØš½āš»
Posted on September 27, 2019
Every TypeScript example and tutorial I have found thus far is about language features, Static typing, Visual Studio, etc. I cannot find anything to tell me how I should be using it with reference to JavaScript and the DOM.
My understanding it you can use TypeScript for the DOM. But, I never see anyone using it for that.
Said johnny in a question on stackoverflow.com. A while back I had the same question. Can We Use Typescript to manipulate the DOM?
Hello world!
Iāve been learning Typescript for a week now. I got into typescript when I wanted to learn the new Angular. Since it is based on Typescript, I decided to learn Typescript. During learning, I found it odd that none of the learning aids I used included examples of using the language with HTML. Every example I saw in those learning aids and some other tutorials I then looked up involved only node.js. More googling landed me on StackOverflow where johnny, as I mentioned before, had the same question. using this as an opportunity to make a post after almost a year, Iāve made this post, the missing piece of the puzzle, in hopes that it would land first instead of johnnyās question on StackOverflow.
Configuration
Using the DOM or Dom manipulation in typescript is simple. All I needed to do was to use the types defined specifically for DOM access that is available in Typescript. The rest was the same as in JavaScript. Butā¦ these āDOM typesā are not available out of the box with Typescript. I needed to explicitly configure the typescript compiler to include the ādomā library in the compilerOptions
section in the configuration file[2] to access the DOM types in my project. āWhy didnāt they include by default?. Maybe the creators didnāt intend to use it primarily for front end developmentā I thought to myself.
Some other configuration changes I made were: I enabled strict
mode for strict type checking and I changed the target
from ācommon JSā to āes5ā, so the compiler can output JS for browsers and not for node.js. I also added the āes2015ā library so that I could use functionalities like arrays and Math functions for my example.
/**
* 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ām going to write a hello world program to demonstrate the use of DOM in typescript. Because itās my first post on typescript. Iāll be covering the basics of using the DOM types and a problem a beginner like me would face while doing this the first time. Iām not covering DOM events here. Iāll be covering them in another article coming soon.
Iāll begin with the basics where I change the inner text value of an existing element. I started by creating an HTML file with a simple html5 boilerplate with a <h1>
element with id greeter saying āhelloā inside the body.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello world</title>
</head>
<body>
<h1 id="greeter">Hello</h1>
</body>
</html>
Then, I opened a new typescript file and added the following code
let greeter:HTMLHeadingElement = document.getElementById("greeter");
greeter.innerText = "Hello world!";
In the code, I created a variable greeter and I assigned the type HTMLHeadingElement
to it. The HTMLHeadingElement
type which is defined in the ādomā library we added to the configuration, tells the compiler that the greeter variable expects an Html heading element and nothing else. And, I assigned the greeter to the value returned by the function getElementById
which returns the element with the ID provided. Then I assigned the string āhello worldā to the innerText
property of the greeter element.
When I compiled the code with the command
:> tsc script.js
It threw the following error
| Type āHTMLElement | nullā is not assignable to type āHTMLHeadingElementā. |
Type ānullā is not assignable to type āHTMLHeadingElementā.
Bummer! My first attempt failed. On the bright side, Typescript is doing its job and the configurations I set up works. The error means that, I tried to assign greeter which is of type HTMLHeadingElement
with an object of type HTMLElement
that the method getElementById
returned. HTMLElement | null
in the error message means that the methodās return value can be either of type HTMLElement
or null
. The special operator |
is called the union operator. I wonāt be explaining āunion typesā in this article. You can learn about them here.
HTMLElement
type is just a common interface for all the html elements[1] but the compiler expects a HTMLHeadingElement
. I thought of changing the greeter variableās type to HTMLElement
but I didnāt. Because, itās not right. If I had changed it to HTMLElement
, it means greeter could accept any HTML element from the DOM. I wanted it to accept only a heading element. So, I used type assertion feature of typescript (Learn about type assertion here) to tell the compiler that the element returned from the getElementById is indeed a heading element and it doesnāt have to worry about it. Hereās the fixed code:
let greeter:HTMLHeadingElement = document.getElementById("greeter") as HTMLHeadingElement;
greeter.innerText = "Hello world!";
Now, the compilation was a success. I included the script.js file generated by the compiler in the Html document and opened it on a browser. It looked like this:
Decoration time
Now that Iāve made sure that everything works as intended, It was time to decorate the page. I wanted a font style that is not formal looking. After browsing through google fonts, I chose Rock Salt. I imported it in my stylesheet along with Dancing Script as a secondary font using CSS imports. I then proceeded by adding a few more elements to the Html document. I centered all the text using CSS flexbox, added a nice background from UI gradients, and adjusted positions of some elements to arrange them properly. The page now looked beautiful.
Next, to place the cherry on top, I wanted to add a pretty background animation of orbs rising to the top like bubbles to the page. To make the orbs I decided to use <div>
elements. Since I wanted several of these orbs with different sizes, I split the task into two so the work could be simplified. One, I created a common style for all the orbs and created a custom animation for the orbs in CSS. And two, I created the orbs dynamically with the help of typescript by creating a set number of <div>
elements, assigning them the style created beforehand and randomizing their sizes, positions, and animation-delay to make them look more natural.
.
.
.
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");
}
.
.
.
Finally, I added the orbs to the dom like this and thereby kickstarting the animation
.
.
.
function releaseBubbles() {
createBubbles();
for (let i = 0; i < bubbleCount; i++) {
containerDiv.appendChild(bubbleBuffer[i]);
}
console.log("Bubbles released");
}
.
.
.
Hereās the final output on YouTube
And the the repo containing the complete code
svijaykoushik / learning-typescript
Examples and demos as part of the series learning typescript on my blog :earn from my experience
Conclusion
During writing this article and 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. If included, it would have confused beginners outright. I think itās best to learn typescript well before starting to use DOM in your projects.
In my example, I skipped the null checking when I fixed the type mismatch error as it seemed unnecessary for the example but you should check for nulls when necessary to avoid breaking your app at runtime. I also skipped the part where I added animations using the animate.css plugin for the text as it felt trivial explaining it.
Finally, I need to thank
Ivan Petrov for suggesting me to read a book when learning a new tech in a commentPosted on September 27, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Thanks for the post and the useful links/images. This particular scenario can really be frustrating :)
Btw have you read a book on git? I found that a good book on git is much more valuable than guides / videos in that scenarios like this one occurred very very, infrequently as a result because of my deeper understanding.
on my previous post
Stop tracking and start ignoring
Vijay Koushik, S. šØš½āš» ć» Feb 17 '19 ć» 2 min read
#git
#untrackfiles
#removefiles
#removefolders
. Thanks, Ivan šš½. The exercises in the book helped me.
Thanks for your time. :)
References
Further Reading