TypeScript Tutorial: Building a Simple Interactive Unit Converter

Have you ever found yourself juggling different units of measurement? Whether you’re baking a cake, planning a trip, or working with scientific data, the need to convert between units is a common one. Wouldn’t it be handy to have a simple, interactive tool that does this for you? In this tutorial, we’ll dive into TypeScript and build just that: a user-friendly unit converter. We’ll cover everything from setting up your project to handling user input and displaying results.

Why TypeScript?

TypeScript, a superset of JavaScript, brings static typing to the language. This means you can catch errors during development, before your code even runs in the browser. This leads to more robust and maintainable code. TypeScript also provides better autocompletion and refactoring capabilities, making your development workflow smoother and more efficient. For our unit converter, this will help us ensure that we’re handling the different units correctly and that our code is easy to understand and modify.

Setting Up Your Project

First, let’s set up our project. We’ll use Node.js and npm (Node Package Manager) for this. If you don’t have them installed, you can download them from the official Node.js website. Open your terminal or command prompt and create a new directory for your project:

mkdir unit-converter
cd unit-converter

Next, initialize a new npm project:

npm init -y

This creates a package.json file, which will manage our project’s dependencies. Now, let’s install TypeScript:

npm install typescript --save-dev

The --save-dev flag indicates that this is a development dependency. We’ll also need to initialize a TypeScript configuration file, tsconfig.json. You can do this by running the following command:

npx tsc --init

This creates a tsconfig.json file in your project directory. This file contains various options for how TypeScript compiles your code. You can customize this file to suit your needs, but for now, we’ll stick with the default settings. Finally, let’s create a directory for our source files, let’s call it src.

mkdir src

Creating the Core Conversion Logic

Now, let’s write the core logic for our unit converter. We’ll start with a simple conversion between meters and feet. Create a file named src/converter.ts and add the following code:


// src/converter.ts

// Define a function to convert meters to feet
function metersToFeet(meters: number): number {
  return meters * 3.28084;
}

// Define a function to convert feet to meters
function feetToMeters(feet: number): number {
  return feet / 3.28084;
}

// Export these functions so we can use them elsewhere
export {
  metersToFeet,
  feetToMeters
};

Here’s a breakdown of the code:

  • We define two functions: metersToFeet and feetToMeters.
  • Each function takes a number as input (either meters or feet) and returns the converted value.
  • We use the conversion factor 3.28084 to convert between meters and feet.
  • The export keyword makes these functions available to other parts of our application.

Building the User Interface (UI) with HTML and JavaScript

Our unit converter needs a user interface. We’ll create a basic HTML page and use JavaScript to interact with our TypeScript code. Create a file named index.html in the root of 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>Unit Converter</title>
</head>
<body>
  <h1>Unit Converter</h1>

  <div>
    <label for="input-value">Enter Value:</label>
    <input type="number" id="input-value">
  </div>

  <div>
    <label for="from-unit">From:</label>
    <select id="from-unit">
      <option value="meters">Meters</option>
      <option value="feet">Feet</option>
    </select>
  </div>

  <div>
    <label for="to-unit">To:</label>
    <select id="to-unit">
      <option value="feet">Feet</option>
      <option value="meters">Meters</option>
    </select>
  </div>

  <button id="convert-button">Convert</button>

  <div id="result"></div>

  <script src="./dist/app.js"></script>
</body>
</html>

This HTML sets up the basic structure of our UI:

  • A heading (<h1>) for the title.
  • An input field (<input type="number">) for the user to enter the value.
  • Two dropdown menus (<select>) for selecting the input and output units.
  • A button (<button>) to trigger the conversion.
  • A div (<div id="result">) to display the converted result.
  • A script tag (<script src="./dist/app.js"></script>) to link to our JavaScript file. We’ll compile our TypeScript code to JavaScript and place it in a dist folder.

Now, let’s create the JavaScript file that will handle the user interaction. Create a file named src/app.ts and add the following code:


// src/app.ts
import { metersToFeet, feetToMeters } from './converter';

const inputValue = document.getElementById('input-value') as HTMLInputElement;
const fromUnit = document.getElementById('from-unit') as HTMLSelectElement;
const toUnit = document.getElementById('to-unit') as HTMLSelectElement;
const convertButton = document.getElementById('convert-button') as HTMLButtonElement;
const resultDiv = document.getElementById('result') as HTMLDivElement;

convertButton?.addEventListener('click', () => {
  const value = parseFloat(inputValue.value);
  const from = fromUnit.value;
  const to = toUnit.value;

  let result: number | null = null;

  if (isNaN(value)) {
    resultDiv.textContent = 'Please enter a valid number.';
    return;
  }

  if (from === to) {
    resultDiv.textContent = 'Input and output units cannot be the same.';
    return;
  }

  try {
    if (from === 'meters' && to === 'feet') {
      result = metersToFeet(value);
    } else if (from === 'feet' && to === 'meters') {
      result = feetToMeters(value);
    }

    if (result !== null) {
      resultDiv.textContent = `Result: ${result.toFixed(2)} ${to}`;
    }
  } catch (error) {
    resultDiv.textContent = 'An error occurred during conversion.';
    console.error(error);
  }
});

This code does the following:

  • Imports the conversion functions from ./converter.
  • Gets references to the HTML elements using their IDs.
  • Adds an event listener to the