Task 1: Get Set Up

Step 1: Introduction to TypeScript

Before we begin, it is important to understand what TypeScript is. TypeScript is a superset of JavaScript that adds static types. This allows us to define the types of values our code can work with, making it more predictable and catching errors early during development.

I recommend reading these relatively short documents before proceeding to the next step. Each document should take about 5 minutes to read.

Step 2: Setting Up the Project

We will create a new Vite project using the pnpm create vite command followed by the name of our project, which we will call quiz-app.

pnpm create vite quiz-app

When prompted, select Vanilla as the project framework, as done in previous projects. However, this time choose TypeScript as the variant.

✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript

Open the src folder and you will notice that the source files have the .ts extension instead of the .js extension. These files are written in TypeScript!

Now, open the counter.ts file and examine its contents:

export function setupCounter(element: HTMLButtonElement) {
  let counter = 0
  const setCounter = (count: number) => {
    counter = count
    element.innerHTML = `count is ${counter}`
  }
  element.addEventListener('click', () => setCounter(counter + 1))
  setCounter(0)
}

Compare it to its counterpart counter.js, which is created when you choose JavaScript as the variant. The counter.js is displayed below for your reference.

export function setupCounter(element) {
  let counter = 0
  const setCounter = (count) => {
    counter = count
    element.innerHTML = `count is ${counter}`
  }
  element.addEventListener('click', () => setCounter(counter + 1))
  setCounter(0)
}

The two code snippets differ in terms of the type annotations used for the function parameters.

In the TypeScript version, the function parameter element is explicitly annotated with the type HTMLButtonElement, indicating that the parameter should be an HTML button element. Additionally, in the TypeScript version, the parameter of the inner function setCounter is annotated with the type number.

This simple example demonstrates that TypeScript is essentially JavaScript with the addition of types.

Next, open package.json and examine the dev dependencies. Take note of the addition of typescript. The "build" script in package.json:

"build": "tsc && vite build"

indicates that running npm run build will first transpile TypeScript code to JavaScript and perform type checking using the tsc command. If the tsc command executes successfully, it will then bundle and optimize your project for production using Vite's build tool capabilities by running vite build.

TypeScript code must be compiled (transpiled) to JavaScript before it can be executed. During the compilation process, TypeScript code is converted to JavaScript code that can be understood and executed by the JavaScript runtime environment.

It is important to note that TypeScript is a development-time tool that provides static type checking and other features to help catch errors and improve code quality during the development process. However, at runtime, when the code is actually executed, it is the JavaScript code that is running.

TypeScript's static type checking helps identify potential issues and errors before the code is compiled and run. It allows developers to catch type-related errors early in the development process, reducing the likelihood of encountering runtime errors.

In summary, TypeScript enhances the development experience by allowing developers to write code with static types, providing better tooling support and catching errors during development. Once the TypeScript code is compiled into JavaScript, it can be executed like any other JavaScript code during runtime.

You should now follow the steps we took to set up the ToDo app project, which are to simplify the scaffolded code and install and configure TailwindCSS and Prettier and deploy the app using GitHub Actions to GitHub Pages. However, make sure that you do not delete tsconfig.json in the root folder or vite-env.ts inside the src folder.

  • The tsconfig.json file is a configuration file for the TypeScript compiler. It specifies the root files and the compiler options required to compile the project.
  • The vite-env.d.ts file is a declaration file used in Vite projects to declare types for global variables or modules, particularly for Vite's environment variables. Vite injects some special types and environment variables, and to get proper type checking and autocompletion for those in TypeScript, you need to have a declaration file like vite-env.d.ts.

Also, download the following favicon.png and add it to the public folder:

favicon.png

Moreover, you may encounter a type checking error when you update your main.ts file with the following code:

import "./style.css";

const app = document.getElementById("app");
app.innerHTML = `<div class="flex items-center justify-center h-screen">
  <div>Hello World!</div>
</div>`;

The error will warn you that app is possibly null. This TypeScript error occurs because document.getElementById("app") can potentially return null if there is no element with the id app in your document (and TypeScript's strict null checks are enabled in tsconfig.json). To fix this, you have a few options:

1. Type Guard

You can perform a null check to ensure app is not null before trying to access its properties:

const app = document.getElementById("app");
if (app !== null) {
  app.innerHTML = `<div class="flex items-center justify-center h-screen">
    <div>Hello World!</div>
  </div>`;
}

2. Non-null Assertion Operator

You can use the non-null assertion operator (!) to tell TypeScript that you are certain that app is not null:

const app = document.getElementById("app")!;

Or place the ! after app:

app!.innerHTML = `<div class="flex items-center justify-center h-screen">
  <div>Hello World!</div>
</div>`;