TypeScript Tutorial: Creating a Simple Web Application for a Number Guessing Game

Are you ready to dive into the world of TypeScript and build something fun and engaging? In this tutorial, we’ll create a simple yet addictive number guessing game. This project is perfect for beginners and intermediate developers looking to solidify their TypeScript skills while creating a functional web application. We’ll cover everything from setting up your development environment to writing the core game logic and providing a user-friendly interface. Along the way, you’ll learn about TypeScript’s core features, such as types, interfaces, and classes, and how they contribute to writing cleaner, more maintainable code. This tutorial is designed to be a hands-on experience, so get ready to code along!

Why Build a Number Guessing Game?

Building a number guessing game is an excellent way to learn and practice fundamental programming concepts. It allows you to:

  • Understand basic control flow (if/else statements, loops).
  • Work with user input and output.
  • Implement simple game logic.
  • Gain experience with event handling.
  • Apply TypeScript’s type system to improve code quality.

Furthermore, it’s a relatively straightforward project, making it ideal for beginners. It also provides a satisfying sense of accomplishment when you complete it. Plus, who doesn’t love a good game?

Setting Up Your Development Environment

Before we start coding, we need to set up our development environment. Here’s what you’ll need:

  • Node.js and npm (Node Package Manager): TypeScript requires Node.js and npm to compile and manage dependencies. You can download them from the official Node.js website.
  • A Code Editor: Choose your favorite code editor. Popular choices include Visual Studio Code (VS Code), Sublime Text, or Atom. VS Code is highly recommended due to its excellent TypeScript support.
  • TypeScript Compiler: We’ll install the TypeScript compiler globally using npm. Open your terminal or command prompt and run:
npm install -g typescript

This command installs the TypeScript compiler globally, allowing you to compile TypeScript files from any directory.

Project Setup

Let’s create our project directory and initialize it:

  1. Create a new directory for your project (e.g., `number-guessing-game`).
  2. Navigate into the project directory in your terminal.
  3. Initialize a `package.json` file by running:
npm init -y

This command creates a `package.json` file with default settings. Now, let’s create a `tsconfig.json` file to configure the TypeScript compiler. Run the following command:

tsc --init

This creates a `tsconfig.json` file with default compiler options. You can customize these options as needed. For this project, the default settings will work well, but it’s good practice to understand some key options. For example, the `target` option specifies the ECMAScript version to compile to (e.g., `ES5`, `ES6`, `ES2015`). The `module` option specifies the module system to use (e.g., `commonjs`, `es2015`). The `outDir` option specifies the output directory for compiled JavaScript files. The `strict` option enables strict type checking.

Creating the HTML Structure

We’ll start by creating the HTML structure for our game. Create an `index.html` file in your project directory and add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Number Guessing Game</title>
 <link rel="stylesheet" href="style.css"> <!-- Link to your CSS file -->
</head>
<body>
 <div class="container">
 <h1>Number Guessing Game</h1>
 <p>Guess a number between 1 and 100:</p>
 <input type="number" id="guessInput">
 <button id="guessButton">Guess</button>
 <p id="feedback"></p>
 <p id="attempts"></p>
 </div>
 <script src="script.js"></script> <!-- Link to your JavaScript file -->
</body>
<style>
 body {
 font-family: sans-serif;
 text-align: center;
 background-color: #f0f0f0;
 }
 .container {
 width: 80%;
 margin: 50px auto;
 padding: 20px;
 background-color: #fff;
 border-radius: 8px;
 box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
 }
 input[type="number"] {
 padding: 10px;
 font-size: 16px;
 border: 1px solid #ccc;
 border-radius: 4px;
 margin-bottom: 10px;
 }
 button {
 padding: 10px 20px;
 font-size: 16px;
 background-color: #4CAF50;
 color: white;
 border: none;
 border-radius: 4px;
 cursor: pointer;
 }
 button:hover {
 background-color: #3e8e41;
 }
 #feedback {
 font-size: 18px;
 margin-top: 10px;
 }
 #attempts {
 font-size: 16px;
 margin-top: 10px;
 }
</style>
</html>

This HTML provides the basic structure for our game, including a title, input field, a guess button, feedback area, and a place to display the number of attempts. We’ve also included a simple CSS style block for basic styling.

Writing the TypeScript Code

Now, let’s write the TypeScript code for our game. Create a file named `script.ts` in your project directory. This is where the game logic will reside. We’ll start by defining the game’s core elements:


// Define the secret number and the maximum number of attempts
const secretNumber = Math.floor(Math.random() * 100) + 1;
let attemptsLeft = 10;
let hasWon = false;

// Get references to HTML elements
const guessInput = document.getElementById('guessInput') as HTMLInputElement;
const guessButton = document.getElementById('guessButton') as HTMLButtonElement;
const feedback = document.getElementById('feedback') as HTMLParagraphElement;
const attemptsDisplay = document.getElementById('attempts') as HTMLParagraphElement;

// Function to update the attempts display
function updateAttemptsDisplay(): void {
 attemptsDisplay.textContent = `Attempts left: ${attemptsLeft}`;
}

// Function to handle the user's guess
function checkGuess(): void {
 if (hasWon) {
 return;
 }

 const guess = parseInt(guessInput.value);

 if (isNaN(guess) || guess < 1 || guess > 100) {
 feedback.textContent = 'Please enter a valid number between 1 and 100.';
 return;
 }

 attemptsLeft--;

 if (guess === secretNumber) {
 feedback.textContent = `Congratulations! You guessed the number ${secretNumber} correctly!`;
 hasWon = true;
 guessButton.disabled = true;
 } else if (attemptsLeft === 0) {
 feedback.textContent = `Game over! The number was ${secretNumber}.`;
 guessButton.disabled = true;
 } else if (guess < secretNumber) {
 feedback.textContent = 'Too low! Try again.';
 } else {
 feedback.textContent = 'Too high! Try again.';
 }

 updateAttemptsDisplay();
}

// Add an event listener to the guess button
guessButton.addEventListener('click', checkGuess);

// Initialize the attempts display
updateAttemptsDisplay();

Let’s break down this code:

  • Secret Number and Attempts: We generate a random secret number between 1 and 100 and set the initial number of attempts.
  • HTML Element References: We get references to the HTML elements using `document.getElementById()`. Using the `as` keyword, we cast these elements to their specific HTML element types (e.g., `HTMLInputElement`, `HTMLButtonElement`, `HTMLParagraphElement`) to enable type safety and provide better code completion.
  • `updateAttemptsDisplay()` Function: This function updates the display of remaining attempts.
  • `checkGuess()` Function: This function is the core of the game logic. It:
    • Gets the user’s guess from the input field.
    • Validates the input to ensure it’s a number between 1 and 100.
    • Decrements the number of attempts.
    • Checks if the guess is correct, too low, or too high.
    • Provides feedback to the user.
    • Updates the attempts display.
  • Event Listener: We add an event listener to the guess button that calls the `checkGuess()` function when the button is clicked.
  • Initialization: We initialize the attempts display.

Compiling and Running the Game

Now, we need to compile our TypeScript code into JavaScript and run the game. Open your terminal and navigate to your project directory. Then, run the following command:

tsc

This command compiles your `script.ts` file into a `script.js` file in the same directory. If you have configured an `outDir` in your `tsconfig.json`, the output file will be placed in that directory.

To run the game, open your `index.html` file in a web browser. You should see the game interface, and you can start guessing numbers. Open your browser’s developer console to check for any errors. If you see any errors, review the code and the console messages to identify and fix them.

Adding More Features

Let’s enhance our game with some additional features to make it more interactive and user-friendly:

1. Reset Button

Add a reset button that allows the user to start a new game without refreshing the page. Add this HTML code inside the <div class=”container”> in your `index.html`:

<button id="resetButton">Reset</button>

Then, add the following code to `script.ts`:


const resetButton = document.getElementById('resetButton') as HTMLButtonElement;

function resetGame(): void {
 secretNumber = Math.floor(Math.random() * 100) + 1;
 attemptsLeft = 10;
 hasWon = false;
 guessInput.value = '';
 guessButton.disabled = false;
 feedback.textContent = '';
 updateAttemptsDisplay();
}

resetButton.addEventListener('click', resetGame);

This code adds a reset button, gets a reference to it, and defines a `resetGame()` function that resets all game variables and UI elements. An event listener is added to the reset button to call the `resetGame()` function when clicked.

2. Displaying Previous Guesses

Keep track of the user’s previous guesses and display them to the user. Add this HTML code inside the <div class=”container”> in your `index.html`:

<p id="previousGuesses">Previous guesses: </p>

Then, modify `script.ts` as follows:


const previousGuessesDisplay = document.getElementById('previousGuesses') as HTMLParagraphElement;
let previousGuesses: number[] = [];

function checkGuess(): void {
 // ... (existing code)

 if (!isNaN(guess) && guess >= 1 && guess <= 100) {
 previousGuesses.push(guess);
 previousGuessesDisplay.textContent = 'Previous guesses: ' + previousGuesses.join(', ');
 }

 // ... (rest of the checkGuess function)
}

function resetGame(): void {
 // ... (existing code)
 previousGuesses = [];
 previousGuessesDisplay.textContent = 'Previous guesses: ';
}

This code adds a `previousGuesses` array to store the guesses and updates the `previousGuessesDisplay` with the user’s guesses.

3. Difficulty Levels

Implement difficulty levels (Easy, Medium, Hard) to control the number of attempts and the range of the secret number. Add this HTML code inside the <div class=”container”> in your `index.html`:

<div id="difficultyOptions">
 <label for="difficulty">Difficulty:</label>
 <select id="difficulty">
 <option value="easy">Easy (10 attempts, 1-100)</option>
 <option value="medium">Medium (7 attempts, 1-100)</option>
 <option value="hard">Hard (5 attempts, 1-100)</option>
 </select>
</div>

And modify `script.ts` accordingly:


const difficultySelect = document.getElementById('difficulty') as HTMLSelectElement;

function setDifficulty(): void {
 const difficulty = difficultySelect.value;
 switch (difficulty) {
 case 'easy':
 attemptsLeft = 10;
 break;
 case 'medium':
 attemptsLeft = 7;
 break;
 case 'hard':
 attemptsLeft = 5;
 break;
 }
 resetGame();
}

difficultySelect.addEventListener('change', setDifficulty);

function resetGame(): void {
 secretNumber = Math.floor(Math.random() * 100) + 1;
 if (difficultySelect.value === 'hard') {
 secretNumber = Math.floor(Math.random() * 50) + 1;
 }
 setDifficulty();
 guessInput.value = '';
 guessButton.disabled = false;
 feedback.textContent = '';
 previousGuesses = [];
 previousGuessesDisplay.textContent = 'Previous guesses:';
 updateAttemptsDisplay();
}

setDifficulty(); // Initialize difficulty on page load

This code adds a select element for difficulty levels, a `setDifficulty()` function to adjust the number of attempts based on the selected difficulty, and modifies the `resetGame()` function to accommodate the new difficulty settings.

Common Mistakes and How to Fix Them

Here are some common mistakes beginners encounter and how to avoid them:

  • Incorrect Element Selection: Ensure you are selecting the correct HTML elements using `document.getElementById()`. Double-check the IDs in your HTML and the corresponding code.
  • Type Errors: TypeScript helps prevent type errors. Make sure you declare the correct types for variables and function parameters. Use type annotations (e.g., `let x: number = 10;`) and type assertions (e.g., `as HTMLInputElement`) to improve code safety.
  • Input Validation: Always validate user input to prevent unexpected behavior. In our game, we validate that the input is a number between 1 and 100.
  • Scope Issues: Be mindful of variable scope. Variables declared inside a function are only accessible within that function. Use global variables (declared outside any function) when needed, but be cautious about overuse.
  • Event Listener Problems: Ensure your event listeners are correctly attached to the elements and that the functions they call are defined correctly.

Key Takeaways

  • TypeScript Fundamentals: You’ve gained practical experience with variables, functions, types, and event handling.
  • DOM Manipulation: You’ve learned how to interact with HTML elements using JavaScript.
  • Game Logic: You’ve implemented fundamental game logic, including input validation, conditional statements, and loops.
  • Code Organization: You’ve learned how to structure your code for readability and maintainability.

FAQ

Here are some frequently asked questions about this project:

  1. How do I run the game?

    Open the `index.html` file in your web browser after compiling your TypeScript code to JavaScript using the `tsc` command.

  2. Why am I getting errors in the console?

    Check the console for error messages. Common issues include incorrect element selection, type mismatches, or syntax errors. Review your code and the error messages carefully.

  3. Can I customize the game?

    Yes! Feel free to add more features, such as scorekeeping, different difficulty levels, or a visual theme. Experiment with the code and have fun!

  4. How do I debug the code?

    Use your browser’s developer tools (usually accessed by right-clicking and selecting “Inspect”) to set breakpoints, inspect variables, and step through the code. Use `console.log()` statements to check the values of variables at different points in your code.

SEO Best Practices

To ensure your game ranks well on search engines, consider these SEO best practices:

  • Keyword Optimization: Naturally incorporate relevant keywords such as “number guessing game,” “TypeScript tutorial,” and “web application” throughout your content.
  • Title and Meta Description: Write a compelling title and meta description that accurately describe your game and tutorial.
  • Header Tags: Use header tags (H2, H3, H4) to structure your content logically and improve readability.
  • Internal Linking: Link to other relevant articles or pages on your blog to improve user engagement and site navigation.
  • Image Optimization: Use descriptive alt text for images to improve accessibility and SEO.
  • Mobile Responsiveness: Ensure your game is responsive and works well on different devices.

This tutorial provides a solid foundation for building a number guessing game in TypeScript. Remember to practice and experiment with different features to enhance your skills. The ability to create interactive web applications is a valuable skill in modern software development. As you continue to build and refine your game, you’ll gain a deeper understanding of TypeScript and web development principles. Happy coding!