;

TypeScript Types


Types are a core feature of TypeScript, helping you write code that is safer, more predictable, and easier to debug. This guide will introduce you to the various types available in TypeScript, from basic types to advanced concepts like union types, literal types, and generics. We’ll also provide real-world examples to illustrate how TypeScript types can be applied in practical scenarios.

Introduction to TypeScript Types

TypeScript is a statically typed language, meaning that variables, parameters, and return values have defined types, which can be checked at compile-time. Types make it easier to catch errors early, improving code quality and making it more reliable. In this guide, we’ll cover everything you need to know about TypeScript types, from fundamental concepts to advanced features.

What Are Types in TypeScript?

Types define the kind of values a variable, function parameter, or return value can hold. They enable TypeScript to enforce type-checking rules, reducing the chances of runtime errors and making your code easier to understand and maintain. TypeScript’s type system includes basic types, advanced types, function types, and more, giving you flexibility and control over how data is handled in your code.

Basic Types

TypeScript includes several basic types that you’ll encounter frequently in your code.

number

The number type represents numeric values. TypeScript doesn’t differentiate between integers and floating-point numbers.

let age: number = 25;
let salary: number = 50000.75;

string

The string type represents text values enclosed in quotes (', ", or `).

let name: string = "Alice";
let message: string = `Hello, ${name}!`;

boolean

The boolean type represents true or false values.

let isActive: boolean = true;
let hasPermission: boolean = false;

array

An array type can hold a collection of values of a specific type. In TypeScript, you can declare arrays in two ways: type[] or Array<type>.

let numbers: number[] = [1, 2, 3];
let fruits: Array<string> = ["apple", "banana", "cherry"];

tuple

A tuple is a fixed-length array with specific types for each position. Tuples are particularly useful for representing structured data.

let person: [string, number];
person = ["Alice", 30];

enum

An enum (enumeration) is a way to define a set of named constants, making your code more readable.

enum Direction {
  North,
  South,
  East,
  West,
}

let travelDirection: Direction = Direction.North;

any

The any type can hold any value, disabling type-checking for that variable. Use any sparingly, as it reduces the benefits of TypeScript’s type system.

let data: any = "Hello";
data = 42; // No error, but be cautious using `any`

Advanced Types

Union Types

Union types allow a variable to hold more than one type, increasing flexibility while maintaining type safety.

let id: string | number;
id = "ABC123";
id = 456;

Intersection Types

Intersection types combine multiple types into one, allowing a variable to satisfy multiple type requirements.

interface Person {
  name: string;
}

interface Employee {
  employeeId: number;
}

type Worker = Person & Employee;

let employee: Worker = {
  name: "Alice",
  employeeId: 101,
};

Literal Types

Literal types allow you to specify exact values for a variable, making it useful for cases where you want to restrict a variable to specific options.

let alignment: "left" | "right" | "center";
alignment = "left"; // Valid
// alignment = "up"; // Error

Type Aliases

Type aliases let you create custom names for complex types, improving code readability and reusability.

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

let coordinates: Point = { x: 10, y: 20 };

Type Inference

TypeScript has a type inference feature, which automatically detects the type of a variable based on its initial value.

let inferredValue = 42; // Inferred as `number`

Function Types

TypeScript allows you to define types for function parameters and return values, improving clarity and type safety.

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

In this example, a and b are number types, and the function is expected to return a number. If you try to pass a non-number argument, TypeScript will throw an error.

Optional and Default Parameters

Parameters can be marked as optional using ?, or you can provide a default value.

function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}`;
}

Object Types and Interfaces

Object Types

In TypeScript, you can define objects with specific types for each property. This helps ensure that objects have the correct structure.

let user: { name: string; age: number } = { name: "Alice", age: 25 };

Interfaces

Interfaces allow you to define the structure of an object, providing consistency across your code.

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

let user: User = { name: "Alice", age: 30 };

Interfaces are often used in TypeScript to describe the shape of data and enforce consistency across objects.

Generics in TypeScript

Generics allow you to write functions and classes that work with various types without losing type safety.

Example of Generics with Functions

function identity<T>(value: T): T {
  return value;
}

let result1 = identity<number>(10);
let result2 = identity<string>("Hello");

Generics are denoted by <T> (or any other letter) and allow the function to operate on different types while maintaining type safety.

Example of Generics with Classes

class Box<T> {
  contents: T;

  constructor(contents: T) {
    this.contents = contents;
  }
}

let numberBox = new Box<number>(123);
let stringBox = new Box<string>("Hello");

Real-World Examples of Using Types

Example 1: Defining a Product Type in an E-Commerce Application

Let’s say you’re building an e-commerce app where each product has a name, price, and optional discount. You can use an interface to define the product type.

interface Product {
  name: string;
  price: number;
  discount?: number;
}

function displayProduct(product: Product): void {
  console.log(`Product: ${product.name}`);
  console.log(`Price: $${product.price}`);
  if (product.discount) {
    console.log(`Discount: ${product.discount}%`);
  }
}

let product1: Product = { name: "Laptop", price: 1200, discount: 10 };
displayProduct(product1);

Example 2: Using Generics in a Data Fetcher Function

Generics are useful for building reusable code, such as a data fetcher that can work with various data types.

async function fetchData<T>(url: string): Promise<T> {
  const response = await fetch(url);
  return response.json() as T;
}

interface User {
  id: number;
  name: string;
}

fetchData<User>("https://api.example.com/user/1").then((user) => {
  console.log(`User: ${user.name}`);
});

In this example, the fetchData function uses generics to specify that the data it returns matches the User interface, providing type safety while fetching data.

Key Takeaways

  1. Basic Types: TypeScript’s basic types, such as number, string, boolean, and array, are fundamental for all TypeScript code.
  2. Advanced Types for Flexibility: Union, intersection, and literal types offer flexibility while maintaining type safety.
  3. Function and Object Types: TypeScript enforces type consistency for function parameters, return values, and objects.
  4. Generics for Reusability: Generics allow you to create reusable components while preserving type safety.
  5. Practical Applications: TypeScript types are useful in real-world applications, from defining data structures to fetching and displaying data.

Summary

Types are at the heart of TypeScript, providing structure and safety that make your code more reliable. This guide has covered basic types, advanced types, function and object types, and generics, showing how each can be used to create safer, more maintainable code. By understanding TypeScript’s type system, you’ll be able to write code that is easier to debug, more predictable, and better suited for large-scale applications. Start exploring these types in your projects and see how TypeScript can improve your coding experience!