TypeScript Setup and Environment

Setting up a proper TypeScript development environment is crucial for a productive workflow. This guide will walk you through the process of installing TypeScript, configuring your development environment, and preparing the essential tools for TypeScript development.

Prerequisites

Before setting up TypeScript, ensure you have the following:

  1. Node.js and npm: TypeScript compiler runs on Node.js
  2. A code editor: Visual Studio Code is recommended for this course
  3. Basic familiarity with command-line operations

Installing TypeScript

A global installation allows you to use the TypeScript compiler tsc from any directory on your system. You can either install it through npm globally, or if you are using homebrew on a MacOS you can install it through homebrew.

After you've installed if, you can check the TypeScript version installed on your machine with the help of tsc --version.

You should see output similar to: Version 5.3.3 (or whatever version is currently installed).

using npm install

npm install -g typescript

using homebrew

brew install typescript

check ts version

tsc --version

For most projects, it's better to install TypeScript locally:

# Create a new directory for your project
mkdir my-typescript-project
cd my-typescript-project

# Initialize a new npm project
npm init -y

# Install TypeScript as a dev dependency
npm install --save-dev typescript

With a local installation, you can run the TypeScript compiler using npx:

npx tsc --version

This approach has several advantages:

  1. Version consistency: Everyone working on the project uses the same TypeScript version
  2. Project isolation: Different projects can use different TypeScript versions
  3. Better CI/CD integration: Continuous integration pipelines will automatically use the correct version

Setting Up Your First TypeScript Project

Let's set up a basic TypeScript project from scratch:

1. Create a Project Structure

To create a new TypeScript project we will need to have some familiarity with the terminal.

mkdir my-typescript-project
cd my-typescript-project
npm init -y
npm install --save-dev typescript

2. Initialize TypeScript Configuration

Create a TypeScript configuration file tsconfig.json:

npx tsc --init

This generates a tsconfig.json file with default settings and helpful comments.

3. Create a Simple TypeScript File

Create a source directory and your first TypeScript file:

mkdir src

Create a file at src/index.ts with the following content:

src/index.ts

function greet(name: string): string {
  return `Hello, ${name}!`;
}

console.log(greet("TypeScript"));

4. Compile Your TypeScript Code

Compile your TypeScript code to JavaScript:

npx tsc

By default, this will look for the tsconfig.json file and compile according to the settings defined there.

5. Run the Compiled JavaScript

node dist/index.js

You should see: Hello, TypeScript!

Configuring TypeScript with tsconfig.json

The tsconfig.json file controls the TypeScript compiler's behavior. Let's explore some important configuration options:

Essential Configuration Properties

Here's a basic tsconfig.json file with commonly used options:

basic tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",           /* Set the JavaScript language version for emitted JavaScript */
    "module": "commonjs",         /* Specify what module code is generated */
    "outDir": "./dist",           /* Specify an output folder for all emitted files */
    "rootDir": "./src",           /* Specify the root folder within your source files */
    "strict": true,               /* Enable all strict type-checking options */
    "esModuleInterop": true,      /* Emit additional JavaScript to ease support for importing CommonJS modules */
    "skipLibCheck": true,         /* Skip type checking all .d.ts files */
    "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports */
  },
  "include": ["src/**/*"],        /* Files to include in compilation */
  "exclude": ["node_modules", "**/*.spec.ts"] /* Files to exclude from compilation */
}

Commonly Used Compiler Options

Target JavaScript Version

The target option specifies which JavaScript version the TypeScript compiler should output:

"target": "es2016" // Options include: es3, es5, es6/es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022

Choose a target based on your deployment environment:

  • For modern browsers: es2016 or newer
  • For older browsers support: es5
  • For Node.js: Match your Node.js version (e.g., Node.js 14+ supports es2020)

Module System

The module option determines which module system the output JavaScript uses:

"module": "commonjs" // Options include: none, commonjs, amd, system, umd, es6/es2015, es2020, ESNext

Choose based on your runtime environment:

  • For Node.js: commonjs
  • For modern browsers or bundlers (webpack, Rollup): es2015 or ESNext

Type Checking Strictness

TypeScript offers various levels of type checking strictness:

"strict": true, // Enables all strict type checking options
// Or enable individual options:
"noImplicitAny": true,           // Raise error on expressions and declarations with an implied 'any' type
"strictNullChecks": true,        // Enable strict null checking
"strictFunctionTypes": true,     // Enable strict checking of function types
"strictPropertyInitialization": true, // Ensure non-undefined class properties are initialized in the constructor
"noImplicitThis": true,          // Raise error on 'this' expressions with an implied 'any' type
"alwaysStrict": true             // Parse in strict mode and emit "use strict" for each source file

For beginners, you might start with "strict": false and gradually enable stricter checks as you become more comfortable with TypeScript. But usually in React Web-App development we use the "strict": true so that we can create more robust webapps.

Source Maps

Source maps help with debugging by mapping compiled JavaScript back to the original TypeScript code:

"sourceMap": true // Generates corresponding .map file

Additional Important Options

Here are some more optional but important options you might want to include in your project:

"outDir": "./dist",         // Output directory for compiled files
"rootDir": "./src",         // Root directory of input files
"declaration": false,       // Generate .d.ts files
"removeComments": true,     // Remove comments in output files
"noEmitOnError": true,      // Do not emit outputs if any errors were reported
"esModuleInterop": true,    // Better interoperability with non-TypeScript modules
"resolveJsonModule": true,  // Allow importing .json files
"allowJs": true,            // Allow JavaScript files to be compiled
"checkJs": true             // Type check JavaScript files

Setting Up an IDE for TypeScript Development

While TypeScript works with any text editor, using an integrated development environment (IDE) with TypeScript support will significantly improve your productivity.

Visual Studio Code (Recommended)

Visual Studio Code (VS Code) is what we'll use in this TypeScript development course. Of course you can use other IDE's if you want.

1. TypeScript Support: VS Code has built-in TypeScript support, including:

  • Syntax highlighting
  • IntelliSense (code completion)
  • Error checking
  • Quick fixes and refactoring

2. Useful Extensions for TypeScript Development:

Setting Up a TypeScript Development Workflow

A robust TypeScript workflow typically includes the following components:

1. Compilation and Watching

For automatic recompilation when files change. This is what you'll usually use when developing with TypeScript, because it compiles the codebase whenever you save a file.

watch for code changes

# Watch mode
npx tsc --watch

To enhance it even further, you can add the following commans to your package.json:

package.json

...
"scripts": {
  "build": "tsc",
  "watch": "tsc --watch"
}
...

And then you can simply run it by typing the command npm run watch in your terminal.

Best Practices for TypeScript Project Setup

1. Structuring Your Project

In all the courses we will go through, a good project structure improves maintainability and is one of the most important things while creating a project.

Example project structure

my-typescript-project/
├─ src/
│  ├─ index.ts           # Application entry point
│  ├─ config/            # Configuration files
│  ├─ controllers/       # Request controllers (for APIs)
│  ├─ models/            # Data models
│  ├─ services/          # Business logic
│  ├─ utils/             # Utility functions
│  ├─ types/             # Type definitions
│  └─ __tests__/         # Test files
├─ dist/                 # Compiled output
├─ node_modules/         # Dependencies
├─ .eslintrc.js          # ESLint configuration
├─ .prettierrc           # Prettier configuration
├─ tsconfig.json         # TypeScript configuration
├─ package.json          # Project metadata and scripts
└─ README.md             # Project documentation

2. Managing Types

Keep your types organized:

  1. Place types close to their usage: For component-specific types, define them in the same file
  2. Create a dedicated types directory: For shared types across the application
  3. Use namespaces or prefixes: For related groups of types (e.g., Api.Response, User.Settings)
  4. Export types from a central location: Create barrel exports for easy imports

Example of a barrel file src/types/index.ts:

// Re-export all types from individual files
export * from "./user";
export * from "./auth";
export * from "./api";

3. Using Declaration Files

Declaration files \*.d.ts let you add type information to existing JavaScript libraries or define global types:

global.d.ts

global.d.tsx

// Add types to an existing module
import "express";

declare module "express" {
  interface Request {
    user?: {
      id: string;
      username: string;
    };
  }
}

module-augmentation.d.ts:

module-augmentation.d.ts

// Add types to an existing module
import "express";

declare module "express" {
  interface Request {
    user?: {
      id: string;
      username: string;
    };
  }
}

TypeScript Fundamentals Exercise

It's time for a simple exercise!

Overview

In this exercise, students will create a basic command-line inventory management system for a bookstore. This will help reinforce TypeScript fundamentals without requiring any frameworks or complex setup. Try to solve this without the solution collapsed.

Exercise Instructions

1. Project Setup

  • Create a new directory for the project named bookstore-inventory
  • Initialize a new npm project
  • Install TypeScript locally to the project
  • Create a basic tsconfig.json file
  • Set up the project structure with a src folder

2. Creating the Data Types

Create a file called types.ts in the src folder and define the following types:

  • Book interface with properties:

    • id (string)
    • title (string)
    • author (string)
    • year (number)
    • genre (string literal type with options: "fiction", "non-fiction", "science", "fantasy")
    • price (number)
    • inStock (boolean)
  • Inventory type representing an array of Book objects

3. Implementing the Inventory Management Features

Create a file called inventory.ts in the src folder and implement the following functions:

  1. addBook: Add a new book to the inventory (with proper type validation)
  2. removeBook: Remove a book from the inventory by ID
  3. searchBooks: Search for books by title, author, or genre
  4. calculateTotalValue: Calculate the total value of all books in inventory
  5. getBooksByGenre: Get all books of a specific genre
  6. displayBook: Display a single book's information

4. Creating the Main Application

Create a file called index.ts in the src folder that:

  1. Imports all the types and functions from the other files
  2. Creates an initial inventory with at least 5 books
  3. Implements a simple command-line menu system using console.log
  4. Allows the user to interact with the inventory through the functions created earlier

5. Building and Running the Application

  1. Add compile and run scripts to the package.json file
  2. Compile the TypeScript code to JavaScript
  3. Run the application and test all the functionality

6. Optional Extensions (for advanced students)

  • Add error handling with custom error types
  • Implement book editing functionality
  • Add persistence by saving the inventory to a JSON file
  • Create a more interactive command-line interface using a library like readline

Evaluation Criteria

  • Correct use of TypeScript types and interfaces
  • Proper implementation of the required functionality
  • Clean, well-organized code
  • Effective use of TypeScript's type checking

Conclusion

Setting up a proper TypeScript environment is an investment that pays dividends throughout the development process. A well-configured project with appropriate tooling will catch errors early, improve code quality, and enhance the development experience for all team members. As you become more comfortable with TypeScript, you can further customize your setup to match your specific needs and preferences. The configuration described in this guide provides a solid foundation from which you can build increasingly sophisticated applications with confidence. In the next section, we'll explore the key differences between TypeScript and JavaScript to deepen your understanding of how TypeScript enhances the JavaScript language.