Contact us

🌍 All

About us

Digitalization

News

Startups

Development

Design

Introduction to TypeScript

Viktor Kharchenko

Nov 16, 20235 min read

Software development

Table of Content

  • What is TypeScript?

  • TypeScript vs. JavaScript

  • Setting Up a TypeScript Development Environment: Your Launchpad to Success

  • TypeScript's Strong Typing System

  • Declaring Variables and Types: The Building Blocks of TypeScript

  • Functions and Interfaces in TypeScript: Crafting Code with Precision

  • Classes and Inheritance: Building Reusable and Extensible Code

  • TypeScript's Compiler

  • TypeScript Best Practices

  • Conclusion

  • FAQ

In the fast-paced world of software development, staying on top of the latest technologies can be a game-changer. Enter TypeScript, a programming language that has been making waves in the developer community. If you're new to the world of TypeScript or wondering what all the buzz is about, you've come to the right place.

What is TypeScript?

TypeScript, in essence, is a statically typed superset of JavaScript. But what does that mean? In simple terms, it's JavaScript with a set of powerful extras. You get all the flexibility and functionality of JavaScript, but with the added benefit of a robust type system. This type system allows you to catch errors during development rather than at runtime, making your code more reliable and maintainable.

Consider this small code snippet:

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

const message = greet("TypeScript");
console.log(message);

In this example, TypeScript's type annotations ensure that the name parameter must be a string, and the greet function must return a string. It catches any type-related mistakes before you even run the code.

Throughout this article, we'll embark on a journey to explore TypeScript from the ground up. We'll dive into its key features, learn how to set up your development environment, and discover real-world applications. Whether you're a seasoned developer or just starting out, TypeScript has something valuable to offer, and by the end of this article, you'll be well on your way to mastering it.

So, let's roll up our sleeves and begin our adventure into the world of TypeScript!

TypeScript vs. JavaScript

At its core, TypeScript and JavaScript share a common ancestry. Both are versatile programming languages used for web development, but they have a fundamental difference that sets them apart: static typing.

JavaScript: The Dynamic Language

JavaScript, often referred to as the "lingua franca" of the web, is a dynamically typed language. What does that mean? In JavaScript, variable types are determined at runtime. You can assign any type of value to a variable, and the interpreter figures it out as your code runs.

For example:

let age = 25; // age is a number
age = "John"; // Now, age is a string (no error)

In JavaScript, this flexibility can be both a blessing and a curse. It allows for rapid development but can lead to runtime errors that are only discovered when your code is executed.

TypeScript: The Statically Typed Superhero

TypeScript, on the other hand, introduces static typing to the JavaScript ecosystem. With TypeScript, you declare the types of your variables, function parameters, and return values in advance, and the TypeScript compiler checks your code for type-related errors during development.

Consider this TypeScript code:

function add(a: number, b: number): number {
  return a + b;
}

const result = add(5, "10"); // Error: Argument of type '"10"' is not assignable to parameter of type 'number'.

In this example, TypeScript catches the type mismatch error before you even run the code. This early detection of errors can save you hours of debugging time and make your code more robust.

So, the choice between TypeScript and JavaScript largely depends on your project's needs. JavaScript remains the go-to for smaller projects or when you want the ultimate flexibility. In contrast, TypeScript shines in larger, more complex applications, where strong typing can prevent many common pitfalls.

In the next sections, we'll dive deeper into TypeScript's static typing and explore how it can benefit your development process.

Setting Up a TypeScript Development Environment: Your Launchpad to Success

Now that you're intrigued by TypeScript's potential, let's roll up our sleeves and prepare our development environment. This step is crucial for a smooth TypeScript experience.

Node.js and npm: The Foundation

Before we dive into TypeScript, ensure you have Node.js and npm (Node Package Manager) installed on your system. TypeScript often goes hand in hand with Node.js, as it allows you to run TypeScript code on the server-side. You can download and install them from the official Node.js website (https://nodejs.org/).

Installing TypeScript

Once Node.js and npm are ready, installing TypeScript is a breeze. Open your terminal and run the following command:

npm install -g typescript

This command installs TypeScript globally on your system, making it accessible from anywhere in your terminal.

Creating Your First TypeScript File

With TypeScript installed, you can start coding! Create a new directory for your project, and within it, create a TypeScript file with a .ts extension. For example, let's create a file named hello.ts:

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

const message = greet("TypeScript");
console.log(message);

Transpiling TypeScript to JavaScript

TypeScript code needs to be transpiled to JavaScript before it can run in browsers or Node.js. Fortunately, TypeScript comes with a handy compiler called tsc. In your terminal, navigate to the directory containing your TypeScript file and run:

tsc hello.ts

This command generates a hello.js file with the equivalent JavaScript code.

Running Your Code

Now that you have the JavaScript version, you can execute your code with Node.js:

node hello.js

Voilà! You've successfully set up your TypeScript development environment and executed your first TypeScript program.

In the next sections, we'll explore TypeScript's powerful type system and delve into practical coding examples to deepen your understanding.

TypeScript's Strong Typing System

In the dynamic world of programming, where variables can change types like chameleons, TypeScript emerges as a steadfast guardian of code integrity. This section delves deep into TypeScript's strong typing system, uncovering its significance and unveiling the power it brings to your development journey.

Cracking the Code on Types

In TypeScript, everything revolves around types. A type defines the shape and characteristics of your data, from numbers and strings to more complex structures like objects and arrays. But TypeScript takes this a step further by enforcing strict type rules during development.

TypeScript's Core Concept: Static Typing

Unlike JavaScript, where types are determined at runtime, TypeScript employs static typing. This means that before your code even runs, TypeScript rigorously checks and confirms the types of your variables, function parameters, and return values. It's like having an eagle-eyed proofreader for your code, ensuring that everything aligns perfectly.

The Power of Type Annotations

TypeScript's strong typing system relies on type annotations—explicit declarations of types. These annotations serve as road signs for TypeScript, guiding it on the correct type path. Consider this function:

function add(a: number, b: number): number {
  return a + b;
}

Here, a and b are explicitly defined as numbers, and the function is expected to return a number. TypeScript will bark if you try to feed it anything else.

A Fortress Against Bugs

Imagine you're building a banking application. A simple type mismatch can lead to catastrophic results. TypeScript acts as a fortress, guarding your application from such disasters. It ensures that you're depositing numbers, not strings, and withdrawing only what's rightfully a number.

let balance: number = 1000;
balance = "one million"; // TypeScript raises the alarm.

This static analysis prevents runtime errors, making your code robust, reliable, and easier to maintain.

Type Inference: The Friendly Detective

While TypeScript is stringent about types, it's also surprisingly intuitive. It can often infer types without explicit annotations. For instance:

let message = "Hello, TypeScript!"; // TypeScript infers 'message' as a string.

TypeScript silently understands that message is a string, sparing you from writing redundant type annotations.

The Versatility of Union Types

TypeScript goes beyond simple types with union types. You can define a variable that can hold multiple types of values. For instance:

let result: number | string;
result = 42;     // Perfectly fine
result = "Hello"; // Also acceptable

This flexibility is invaluable when dealing with data that can vary.

Enumerated Joy with Enums

Enums provide a way to give friendly names to sets of numeric values. They make your code more expressive and less error-prone. Here's an example:

enum Direction {
  UP = ‘UP’,
  DOWN = ‘DOWN’’,
  LEFT = ‘LEFT’,
  RIGHT = ‘RIGHT’,
}

let move: Direction = Direction.UP;

This makes your code more readable and helps avoid hard-to-debug mistakes.

Enhanced Code Documentation

With TypeScript's type annotations, your code becomes self-documenting. Developers can instantly understand the types of variables and the expected input and output of functions just by looking at the code. This can save hours of sifting through documentation or guessing.

TypeScript's strong typing system is like a trustworthy companion on your coding adventures. It's there to catch errors, provide clarity, and enhance your code's robustness. Whether you're building a simple webpage or a complex enterprise application, TypeScript's type superpower will be your ally in delivering high-quality software.

Declaring Variables and Types: The Building Blocks of TypeScript

In the world of TypeScript, declaring variables and specifying their types is like laying the foundation for a sturdy skyscraper. Let's dive into how TypeScript handles variables and types to create robust and predictable code.

Understanding Variable Declaration

In TypeScript, you declare variables using the let, const, or var keywords, just like in JavaScript. However, TypeScript encourages the use of let and const for better code predictability.

let age: number = 30; // Declaring a number variable
const name: string = "John"; // Declaring a string variable

Notice the colon (:) followed by the type (number or string). This is called a type annotation, which explicitly states the expected data type for the variable.

Type Annotations vs. Type Inference

While type annotations provide clear guidance to TypeScript, the language is also capable of type inference. In simple terms, TypeScript can often figure out the type of a variable based on its initial value. For example:

let score = 100; // TypeScript infers 'score' as a number.

Here, you haven't explicitly specified the type, but TypeScript deduces it from the value assigned.

Arrays and Type Annotations

Arrays in TypeScript can also have type annotations:

let numbers: number[] = [1, 2, 3, 4, 5]; // An array of numbers

This declares an array that can only contain numbers. TypeScript will flag an error if you try to add anything else.

Objects and Interfaces

When dealing with complex data structures like objects, TypeScript introduces interfaces to define their shapes:

interface Person {
  name: string;
  age: number;
}

let user: Person = {
  name: "Alice",
  age: 28,
};

Here, the Person interface defines the expected structure for the user object, ensuring that it has a name (a string) and an age (a number).

Type Aliases for Clarity

In cases where you need to create reusable type definitions, TypeScript offers type aliases:

type Point = {
  x: number;
  y: number;
};

let origin: Point = { x: 0, y: 0 };

Type aliases make your code more readable by giving descriptive names to complex types.

By mastering the art of declaring variables and types in TypeScript, you establish a solid foundation for writing maintainable and error-free code. In the next sections, we'll explore TypeScript's functions, classes, and other advanced features that take your code to the next level.

Functions and Interfaces in TypeScript: Crafting Code with Precision

In TypeScript, functions are not just blocks of code; they are structured entities with clear rules and interfaces. This section unveils how TypeScript empowers developers to create functions that are both reliable and well-documented.

Defining Function Signatures

In TypeScript, you can define a function's signature using type annotations. Let's consider a simple example of a function that adds two numbers:

function add(a: number, b: number): number {
  return a + b;
}

Here, we declare that add is a function that takes two parameters (a and b) of type number and returns a value of type number. TypeScript enforces these rules, helping you catch type-related errors early.

Function Interfaces

Interfaces play a pivotal role when defining the structure of functions. They describe the expected shape of function parameters and return values. For instance:

interface Calculator {
  (a: number, b: number): number;
}

const add: Calculator = (a, b) => a + b;
const subtract: Calculator = (a, b) => a - b;

Here, the Calculator interface defines a function that takes two numbers and returns a number. Both add and subtract adhere to this interface, ensuring consistency across your codebase.

Optional and Default Parameters

In TypeScript, you can mark function parameters as optional using the ? symbol:

function greet(name: string, age?: number): string {
  if (age !== undefined) {
    return `Hello, ${name}, you are ${age} years old.`;
  } else {
    return `Hello, ${name}.`;
  }
}

This flexibility allows you to call the greet function with or without specifying the age parameter.

Rest Parameters

To work with a variable number of arguments, TypeScript provides rest parameters:

function average(...numbers: number[]): number {
  const sum = numbers.reduce((acc, val) => acc + val, 0);
  return sum / numbers.length;
}

Here, ...numbers allows you to pass any number of arguments to the average function, and TypeScript treats them as an array of numbers.

Callbacks and Function Types

In TypeScript, you can specify function types when dealing with callbacks or higher-order functions. For example:

function doSomethingAsync(callback: (result: string) => void) {
  setTimeout(() => {
    const data = "Done!";
    callback(data);
  }, 1000);
}

Here, the callback parameter is defined as a function that takes a string and returns void, indicating it doesn't return any value.

By understanding and harnessing TypeScript's functions and interfaces, you can create well-structured, type-safe, and highly maintainable code. In the upcoming sections, we'll explore TypeScript's class-based object-oriented programming features and delve into practical coding examples to enhance your expertise.

Classes and Inheritance: Building Reusable and Extensible Code

In TypeScript, classes are the cornerstone of object-oriented programming, enabling you to model real-world entities and create code that's both organized and extendable. In this section, we'll embark on a journey into the world of classes and inheritance.

Defining Classes

A class in TypeScript is a blueprint for creating objects. It encapsulates properties (attributes) and methods (functions) that define the behaviour of objects.

class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

const alice = new Person("Alice", 30);
alice.greet(); // Outputs: Hello, my name is Alice and I am 30 years old.

In this example, we've defined a Person class with properties name and age, and a greet method to introduce themselves.

Constructors and Initialization

The constructor method is called when an object is created from a class. It initialises the object's properties. TypeScript allows you to specify the access modifier (public, private, or protected) in front of constructor parameters to control their visibility and accessibility.

Inheritance

Inheritance is a fundamental concept in object-oriented programming, and TypeScript supports it fully. You can create a new class by extending an existing one, inheriting its properties and methods.

class Student extends Person {
  studentId: number;

  constructor(name: string, age: number, studentId: number) {
    super(name, age);
    this.studentId = studentId;
  }

  study() {
    console.log(`${this.name} is studying.`);
  }
}

const bob = new Student("Bob", 25, 12345);
bob.greet(); // Inherits 'greet' from Person
bob.study(); // Outputs: Bob is studying.

Here, the Student class extends the Person class, inheriting its name property and greet method. It also introduces its own property studentId and a study method.

Access Modifiers

TypeScript provides access modifiers like public, private, and protected to control the visibility of class members. For example, using private restricts access to a member within the class:

class BankAccount {
  private balance: number;

  constructor(initialBalance: number) {
    this.balance = initialBalance;
  }

  public withdraw(amount: number) {
    if (amount <= this.balance) {
      this.balance -= amount;
      console.log(`Withdrawn ${amount}. New balance: ${this.balance}`);
    } else {
      console.log("Insufficient funds.");
    }
  }
}

const account = new BankAccount(1000);
account.withdraw(500); // Allowed
console.log(account.balance); // Error: Property 'balance' is private.

By embracing classes and inheritance in TypeScript, you can create organised, reusable, and extensible code that models real-world entities effectively. In the upcoming sections, we'll delve deeper into TypeScript's advanced features and practical coding examples to enhance your development skills.

TypeScript's Compiler

Meet the wizard behind the TypeScript magic: the TypeScript Compiler, often referred to as tsc. This tool is responsible for transforming your TypeScript code into JavaScript, making it compatible with browsers and Node.js. Let's uncover the power of tsc.

What is tsc?

The TypeScript Compiler (tsc) is a command-line tool that takes your TypeScript files and compiles them into JavaScript files. It ensures that your TypeScript code, with its strong typing and modern features, can run on any JavaScript runtime.

Simple Compilation

Using tsc is straightforward. Suppose you have a TypeScript file named app.ts. You can compile it into JavaScript by running:

tsc app.ts

This command generates an app.js file, ready for execution.

Configuration Files

For larger projects, TypeScript allows you to create a tsconfig.json file to configure compilation options. This file specifies things like the target JavaScript version, module system, and output directory. It simplifies the compilation process and maintains consistency across your project.

Watching for Changes

tsc can watch your files and automatically recompile when changes occur. Use the -w or --watch flag:

tsc -w

This is immensely helpful during development, as it keeps your JavaScript files up-to-date as you make changes to your TypeScript code.

Strict Mode

TypeScript offers strict compilation options (--strict) that enforce best practices and catch potential errors. Enabling strict mode helps you write safer and more maintainable code.

Integration with Build Systems

Many build tools, such as Webpack and Gulp, integrate seamlessly with tsc. This allows you to incorporate TypeScript compilation into your existing build pipelines for web applications.

In summary, tsc is your trusty companion in the TypeScript journey. It takes your typed, modern code and compiles it into JavaScript that's ready to run anywhere. Whether you're building web apps, server applications, or libraries, tsc is an essential tool for TypeScript developers.

TypeScript Best Practices

While TypeScript offers powerful features, using it effectively involves adhering to best practices. These practices ensure your code remains clean, maintainable, and error-free. Let's explore some essential TypeScript best practices that will elevate your development journey.

1. Enable Strict Mode

Enabling TypeScript's strict mode (--strict) is the foundation of writing robust code. It enforces stronger type checking, helps prevent common mistakes, and encourages best practices.

tsc --strict yourFile.ts

2. Use Descriptive Variable Names

Choose descriptive names for your variables, functions, and classes. Clear naming enhances code readability and reduces the need for comments.

// Not recommended
const a = "John";

// Recommended
const userName = "John";

3. Leverage Type Inference

Let TypeScript infer types whenever possible, rather than explicitly specifying them. This reduces redundancy and keeps your code concise.

// Not necessary
const age: number = 30;

// TypeScript infers the type
const age = 30;

4. Avoid Any Type

Limit the use of the any type. It should be used sparingly when working with external libraries or when type information is genuinely unknown.

// Use with caution
function processData(data: any) {
  // ...
}

5. Embrace TypeScript's Built-in Types

Leverage TypeScript's built-in types like Array, Object, Promise, and others instead of creating custom types when applicable.

const numbers: number[] = [1, 2, 3];
const person: Record<string, any> = { name: "Alice", age: 30 };

6. Use Interfaces for Object Shapes

When defining the shape of an object, prefer interfaces over type aliases. Interfaces are more suitable for defining contracts, and they can be extended or implemented more easily.

// Interface
interface Person {
  name: string;
  age: number;
}

// Type alias
type Person = {
  name: string;
  age: number;
};

7. Document Your Code

Include comments and documentation for complex code, non-trivial functions, and interfaces to help other developers understand your codebase.

/**
 * Calculates the sum of two numbers.
 * @param a - The first number.
 * @param b - The second number.
 * @returns The sum of a and b.
 */
function add(a: number, b: number): number {
  return a + b;
}

By following these TypeScript best practices, you'll ensure your codebase remains clean, maintainable, and error-resistant. TypeScript's strong typing system becomes even more powerful when paired with these guidelines, making your development experience smoother and more efficient.

Conclusion

Congratulations! You've embarked on a thrilling journey into the world of TypeScript. You've learned how TypeScript's strong typing system can catch errors before they happen, how to declare variables and types effectively, and the art of crafting classes and interfaces for structured code.

You've also discovered TypeScript's compiler (tsc), your trusty ally in transforming TypeScript into JavaScript, and you've embraced best practices to keep your code clean and maintainable.

As you venture further into the TypeScript landscape, remember that this is just the beginning. TypeScript's versatility shines in web development, server-side scripting, and more. Whether you're building a small web app or a complex enterprise solution, TypeScript equips you with powerful tools to create efficient, reliable, and scalable code.

Keep exploring, keep coding, and let TypeScript be your guide to a brighter and more productive coding future. Your TypeScript journey has just begun!

FAQ

What is TypeScript, and why should I use it?

TypeScript is a statically typed superset of JavaScript that brings type safety and enhanced tooling to your code, making it more reliable and maintainable.

How does TypeScript differ from JavaScript?

TypeScript adds static typing, interfaces, and other features to JavaScript, making it more robust and suitable for large-scale applications.

How do I set up a TypeScript development environment?

You can set up a TypeScript environment by installing Node.js, npm, and the TypeScript compiler (tsc) globally on your system.

What is the TypeScript compiler (tsc)?

tsc is a command-line tool that converts TypeScript code into JavaScript, making it compatible with browsers and Node.js.

What are some best practices for writing TypeScript code?

Best practices include enabling strict mode, using descriptive variable names, and preferring TypeScript's built-in types over custom ones.

What are TypeScript interfaces used for?

Interfaces define the structure of objects, making your code more readable and providing clear contracts for functions and classes.

How can I extend a class in TypeScript?

You can extend a class using the extends keyword to inherit properties and methods from a parent class.

What are access modifiers in TypeScript?

Access modifiers like public, private, and protected control the visibility of class members, ensuring encapsulation and code security.

How do I compile TypeScript code?

Use the TypeScript Compiler (tsc) to compile TypeScript files into JavaScript. You can also configure compilation options in a tsconfig.json file.

What is type inference in TypeScript?

Type inference is TypeScript's ability to automatically determine variable types based on their initial values, reducing the need for explicit type annotations.

When should I use the any type in TypeScript?

The any type should be used sparingly when dealing with dynamic or unknown types, but it's best to avoid it whenever possible for type safety.

What are rest parameters in TypeScript?

Rest parameters allow functions to accept a variable number of arguments as an array, simplifying the handling of multiple inputs.

How can I document my TypeScript code effectively?

Use comments and JSDoc-style documentation to explain your code's functionality, making it easier for others (and yourself) to understand and maintain.

Can TypeScript be used with popular build tools?

Yes, TypeScript can be seamlessly integrated with build tools like Webpack, Gulp, and others, allowing you to incorporate TypeScript compilation into your workflow.

What are some advanced features of TypeScript?

TypeScript offers advanced features like union types, enums, generics, decorators, and conditional types, which enhance code expressiveness and flexibility.

How do I handle asynchronous operations in TypeScript?

TypeScript supports asynchronous programming using features like async/await, Promises, and callbacks to ensure non-blocking code execution.

What are the benefits of using TypeScript in frontend development?

TypeScript enhances frontend development by reducing runtime errors, improving code maintainability, and providing better tooling and editor support.

Can I use TypeScript for server-side development?

Yes, TypeScript can be used for server-side development with frameworks like Node.js and popular libraries like Express, making backend code more robust.

Is TypeScript suitable for building large-scale applications?

Yes, TypeScript's strong typing and advanced features make it an excellent choice for building large, complex applications with improved code quality.

Where can I find resources to further my TypeScript knowledge?

You can explore TypeScript documentation, online courses, blogs, and community forums to deepen your understanding and stay up-to-date with TypeScript developments.

 
Introduction to TypeScript

Published on November 16, 2023

Share


Viktor Kharchenko Node.js Developer

Don't miss a beat - subscribe to our newsletter
I agree to receive marketing communication from Startup House. Click for the details

You may also like...

Understanding Event-Driven Programming: A Simple Guide for Everyone
Digital productsSoftware development

Understanding Event-Driven Programming: A Simple Guide for Everyone

Explore the essentials of event-driven programming. Learn how this responsive paradigm powers interactive applications with real-world examples and key concepts.

Marek Pałys

Apr 30, 20249 min read

Navigating the Cloud: Understanding SaaS, PaaS, and IaaS
Software developmentDigital products

Navigating the Cloud: Understanding SaaS, PaaS, and IaaS

Discover the differences between SaaS, PaaS, and IaaS in cloud computing. This guide explains each model, their benefits, real-world use cases, and how to select the best option to meet your business goals.

Marek Pałys

Dec 12, 202411 min read

Cypress or Selenium: Making the Right Choice for Your Testing Needs
Product developmentSoftware development

Cypress or Selenium: Making the Right Choice for Your Testing Needs

Cypress and Selenium are leading automated testing tools for web applications. Cypress offers speed, real-time feedback, and ease of setup, while Selenium supports multiple languages, browsers, and platforms for broader testing. Choosing the right tool depends on your project scope, testing needs, and environment.

Alexander Stasiak

Nov 26, 20245 min read

Let's talk
let's talk

Let's build

something together

Startup Development House sp. z o.o.

Aleje Jerozolimskie 81

Warsaw, 02-001

VAT-ID: PL5213739631

KRS: 0000624654

REGON: 364787848

Contact us

Follow us

logologologologo

Copyright © 2025 Startup Development House sp. z o.o.

EU ProjectsPrivacy policy