Learning TypeScript: Hello world with DOM manipulation

svijaykoushik

Vijay Koushik, S. šŸ‘ØšŸ½ā€šŸ’»

Posted on September 27, 2019

Learning TypeScript: Hello world with DOM manipulation

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"
    }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Then, I opened a new typescript file and added the following code

let greeter:HTMLHeadingElement = document.getElementById("greeter");

greeter.innerText = "Hello world!";
Enter fullscreen mode Exit fullscreen mode

Typescript type declaration

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
Enter fullscreen mode Exit fullscreen mode

Typescript type declaration

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!";
Enter fullscreen mode Exit fullscreen mode

Typescript type declaration

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:

Typescript type declaration

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.

Typescript type declaration

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");

}
.
.
.
Enter fullscreen mode Exit fullscreen mode

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");

}
.
.
.
Enter fullscreen mode Exit fullscreen mode

Hereā€™s the final output on YouTube

And the the repo containing the complete code

GitHub logo 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 comment

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.

</div>
Enter fullscreen mode Exit fullscreen mode

on my previous post
. Thanks, Ivan šŸ‘šŸ½. The exercises in the book helped me.

Thanks for your time. :)

References

  1. Interface HTMLElement - http://definitelytyped.org/docs/flipsnap--flipsnap/interfaces/htmlelement.html
  2. Missing basic DOM types in TypeScript project - https://stackoverflow.com/a/42604094

Further Reading

  1. Stop tracking and start ignoring: A tip to delete files from a repository and stop tracking them while keeping them locally - https://svijaykoushik.github.io/blog/2019/02/17/start-ignoring/
  2. TypeScript Tutorial - https://www.tutorialspoint.com/typescript/.
  3. Programming Typescript by Boris Cherny - ISBN 9781492037651
  4. Advanced types in Typescript - https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types
  5. Type Assertion in Typescript - https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions
  6. Learn TypeScript in 50 Minutes - https://youtu.be/WBPrJSw7yQA
šŸ’– šŸ’Ŗ šŸ™… šŸš©

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related