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:
Node.js and npm: TypeScript compiler runs on Node.js
A code editor: Visual Studio Code is recommended for this course
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).
# global install over npm
npm install -g typescript
# installation over homebrew (MacOS)
brew install typescript
# check ts version after installation
tsc --version
Project-Based Installation (Recommended)
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:
Version consistency: Everyone working on the project uses the same TypeScript version
Project isolation: Different projects can use different TypeScript versions
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:
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:
{
"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 newerFor 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
orESNext
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:
ESLint dbaeumer.vscode-eslint: Integrates ESLint into VS Code
Prettier esbenp.prettier-vscode: Code formatter
Path Intellisense christian-kohler.path-intellisense: Autocompletes filenames
Error Lens Alexander.errorlens: Enhances error visibility
BiomeJS biomejs.biomejs: A toolchain of the web. This is my personal favourite and I use it on my personal projects instead of ESLint and Prettier, since it comes out of the box with these functionalities as well it's stricter and you can opt out of rules.
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 mode
npx tsc --watch
To enhance it even further, you can add the following commans to your 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.
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:
Place types close to their usage: For component-specific types, define them in the same file
Create a dedicated types directory: For shared types across the application
Use namespaces or prefixes: For related groups of types (e.g., Api.Response,
User.Settings
)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
// Add types to an existing module
import "express";
declare module "express" {
interface Request {
user?: {
id: string;
username: string;
};
}
}
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.
Beginner TypeScript Exercise: Temperature Converter
Exercise Overview
In this exercise, you will create a very simple temperature conversion program that converts temperatures between Celsius and Fahrenheit. This exercise is designed to help you get comfortable with the most basic TypeScript types without any advanced features.
Learning Goals
Use basic TypeScript types (number, string, boolean)
Create simple functions with type annotations
Practice basic TypeScript syntax
Understand how to compile and run TypeScript code
Detailed Instructions
Step 1: Set Up Your Project
Create a new folder named
temperature-converter
Open your command line and navigate to this folder
Initialize a new npm project by running:
npm init -y
Install TypeScript by running:
npm install typescript --save-dev
Create a
tsconfig.json
file with very basic settings:
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"outDir": "./dist",
"strict": true
}
}
Step 2: Create Your TypeScript File
Create a new file called converter.ts
in your project folder.
Step 3: Implement Temperature Conversion Functions
In converter.ts
, implement the following:
A function that converts Celsius to Fahrenheit
A function that converts Fahrenheit to Celsius
A function that displays the conversion result
Each function should have proper type annotations for parameters and return values.
Step 4: Add Test Cases
Add several test cases to try different temperature conversions.
Step 5: Compile and Run Your Code
Compile your TypeScript code by running:
npx tsc
Run the compiled JavaScript file:
node dist/converter.js
Complete Solution
/**
* Converts a temperature from Celsius to Fahrenheit
* @param celsius Temperature in Celsius
* @returns Temperature in Fahrenheit
*/
function celsiusToFahrenheit(celsius: number): number {
return (celsius * 9) / 5 + 32;
}
/**
* Converts a temperature from Fahrenheit to Celsius
* @param fahrenheit Temperature in Fahrenheit
* @returns Temperature in Celsius
*/
function fahrenheitToCelsius(fahrenheit: number): number {
return ((fahrenheit - 32) * 5) / 9;
}
/**
* Displays the temperature conversion result
* @param originalValue Original temperature value
* @param convertedValue Converted temperature value
* @param fromUnit Original temperature unit
* @param toUnit Target temperature unit
*/
function displayConversion(
originalValue: number,
convertedValue: number,
fromUnit: string,
toUnit: string
): void {
console.log(
`${originalValue} degrees ${fromUnit} is equal to ${convertedValue.toFixed(1)} degrees ${toUnit}`
);
}
// Test cases
function runTests(): void {
console.log("Temperature Converter");
console.log("--------------------");
// Test case 1: Convert 0°C to Fahrenheit
const freezingCelsius: number = 0;
const freezingFahrenheit: number = celsiusToFahrenheit(freezingCelsius);
displayConversion(freezingCelsius, freezingFahrenheit, "Celsius", "Fahrenheit");
// Test case 2: Convert 100°C to Fahrenheit
const boilingCelsius: number = 100;
const boilingFahrenheit: number = celsiusToFahrenheit(boilingCelsius);
displayConversion(boilingCelsius, boilingFahrenheit, "Celsius", "Fahrenheit");
// Test case 3: Convert 32°F to Celsius
const freezingPointF: number = 32;
const freezingPointC: number = fahrenheitToCelsius(freezingPointF);
displayConversion(freezingPointF, freezingPointC, "Fahrenheit", "Celsius");
// Test case 4: Convert 98.6°F (body temperature) to Celsius
const bodyTempF: number = 98.6;
const bodyTempC: number = fahrenheitToCelsius(bodyTempF);
displayConversion(bodyTempF, bodyTempC, "Fahrenheit", "Celsius");
}
// Run the tests
runTests();
Explanation
Basic Types Used:
number
: For temperature valuesstring
: For unit namesvoid
: For functions that don't return a value
Function: celsiusToFahrenheit
Takes a number parameter (the temperature in Celsius)
Returns a number (the temperature in Fahrenheit)
Uses the formula: F = (C × 9/5) + 32
Function: fahrenheitToCelsius
Takes a number parameter (the temperature in Fahrenheit)
Returns a number (the temperature in Celsius)
Uses the formula: C = (F - 32) × 5/9
Function: displayConversion
Takes parameters for the original value, converted value, and unit names
Has a return type of
void
because it only logs to the consoleUses string interpolation to format the output
Function: runTests
Creates various test cases for temperature conversions
Calls the conversion functions with different values
Displays the results using the displayConversion function
Expected Output
When you run this program, you should see output like:
Temperature Converter
--------------------
0 degrees Celsius is equal to 32.0 degrees Fahrenheit
100 degrees Celsius is equal to 212.0 degrees Fahrenheit
32 degrees Fahrenheit is equal to 0.0 degrees Celsius
98.6 degrees Fahrenheit is equal to 37.0 degrees Celsius
Next Steps for Learning
After completing this exercise, you might want to:
Add input validation to check that temperature values are valid numbers
Add support for the Kelvin temperature scale
Create a simple command-line interface to accept user input
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.