Skip to lesson

learningtypescript.org / basics / 05-data-structures · lesson 5 of 25

TL;DR

Learn typed arrays, tuples, and objects in TypeScript. Build type-safe data structures with interfaces, readonly, and generics.

Key concepts

  • TypeScript arrays
  • TypeScript tuples
  • typed data structures
  • TypeScript objects

Data Structures in TypeScript

In this lesson, we'll explore TypeScript's data structures, including arrays, objects, tuples, and more. These structures help you organize and manage data effectively in your programs.

Arrays

Arrays store ordered collections of values of the same type:

Basic Arrays

// Array of numbers
const numbers: number[] = [1, 2, 3, 4, 5];
console.log(`Numbers: ${numbers}`);

// Alternative syntax
const fruits: Array<string> = ["apple", "banana", "orange"];
console.log(`Fruits: ${fruits}`);

// Accessing elements
console.log(`First fruit: ${fruits[0]}`);
console.log(`Last fruit: ${fruits[fruits.length - 1]}`);

Array Methods

const numbers: number[] = [1, 2, 3, 4, 5];

// Push: Add to end
numbers.push(6);
console.log(`After push: ${numbers}`);

// Pop: Remove from end
const last = numbers.pop();
console.log(`Popped: ${last}, Array: ${numbers}`);

// Shift: Remove from beginning
const first = numbers.shift();
console.log(`Shifted: ${first}, Array: ${numbers}`);

// Unshift: Add to beginning
numbers.unshift(0);
console.log(`After unshift: ${numbers}`);

Array Iteration

const fruits: string[] = ["apple", "banana", "orange"];

// forEach
console.log("Using forEach:");
fruits.forEach((fruit, index) => {
  console.log(`${index}: ${fruit}`);
});

// map
const upperFruits = fruits.map(fruit => fruit.toUpperCase());
console.log(`Uppercase: ${upperFruits}`);

// filter
const longFruits = fruits.filter(fruit => fruit.length > 5);
console.log(`Long fruits: ${longFruits}`);

// reduce
const numbers: number[] = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(`Sum: ${sum}`);

Objects

Objects store key-value pairs and can represent complex data:

Basic Objects

// Object with type annotation
const person: { name: string; age: number; city: string } = {
  name: "Alice",
  age: 30,
  city: "New York"
};

console.log(`Name: ${person.name}`);
console.log(`Age: ${person.age}`);
console.log(`City: ${person.city}`);

Type Aliases

// Define a reusable type
type Person = {
  name: string;
  age: number;
  email?: string; // Optional property
};

const alice: Person = {
  name: "Alice",
  age: 30,
  email: "alice@example.com"
};

const bob: Person = {
  name: "Bob",
  age: 25
  // email is optional
};

console.log(`Alice: ${alice.name}, ${alice.email}`);
console.log(`Bob: ${bob.name}`);

Interfaces

// Interface for object shape
interface Product {
  id: number;
  name: string;
  price: number;
  inStock: boolean;
}

const laptop: Product = {
  id: 1,
  name: "Laptop",
  price: 999.99,
  inStock: true
};

console.log(`Product: ${laptop.name}, Price: $${laptop.price}`);

Nested Objects

interface Address {
  street: string;
  city: string;
  zipCode: string;
}

interface User {
  name: string;
  address: Address;
}

const user: User = {
  name: "Alice",
  address: {
    street: "123 Main St",
    city: "New York",
    zipCode: "10001"
  }
};

console.log(`${user.name} lives at ${user.address.street}, ${user.address.city}`);

Tuples

Tuples are fixed-length arrays with specific types for each position:

// Tuple: [string, number]
const person: [string, number] = ["Alice", 30];

console.log(`Name: ${person[0]}, Age: ${person[1]}`);

// Tuple with multiple types
const employee: [number, string, boolean] = [1, "Bob", true];
console.log(`ID: ${employee[0]}, Name: ${employee[1]}, Active: ${employee[2]}`);

// Destructuring tuples
const [name, age] = person;
console.log(`Destructured - Name: ${name}, Age: ${age}`);

Enums

Enums define a set of named constants:

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

const currentDirection: Direction = Direction.North;
console.log(`Direction: ${currentDirection}`); // Prints: 0

// String enum
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

const favoriteColor: Color = Color.Blue;
console.log(`Favorite color: ${favoriteColor}`); // Prints: BLUE

Maps

Maps store key-value pairs with any type as keys:

// Create a Map
const scores = new Map<string, number>();

// Add entries
scores.set("Alice", 95);
scores.set("Bob", 87);
scores.set("Charlie", 92);

// Get values
console.log(`Alice's score: ${scores.get("Alice")}`);

// Check if key exists
console.log(`Has Bob? ${scores.has("Bob")}`);

// Iterate over entries
console.log("All scores:");
scores.forEach((score, name) => {
  console.log(`${name}: ${score}`);
});

Sets

Sets store unique values:

// Create a Set
const uniqueNumbers = new Set<number>();

// Add values
uniqueNumbers.add(1);
uniqueNumbers.add(2);
uniqueNumbers.add(3);
uniqueNumbers.add(2); // Duplicate, won't be added

console.log(`Set size: ${uniqueNumbers.size}`);

// Check if value exists
console.log(`Has 2? ${uniqueNumbers.has(2)}`);

// Iterate over values
console.log("Values:");
uniqueNumbers.forEach(num => {
  console.log(num);
});

Try It Yourself

Practice working with data structures in the playground below:

// Arrays
const numbers: number[] = [5, 10, 15, 20, 25];

console.log("Original array:", numbers);

// Array methods
const doubled = numbers.map(n => n * 2);
console.log("Doubled:", doubled);

const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log("Even numbers:", evenNumbers);

const sum = numbers.reduce((total, n) => total + n, 0);
console.log("Sum:", sum);

// Objects
interface Book {
  title: string;
  author: string;
  year: number;
  pages: number;
}

const book: Book = {
  title: "TypeScript Handbook",
  author: "TypeScript Team",
  year: 2024,
  pages: 300
};

console.log(`\nBook: ${book.title} by ${book.author}`);
console.log(`Published: ${book.year}, Pages: ${book.pages}`);

// Tuples
const coordinate: [number, number] = [10, 20];
console.log(`\nCoordinate: (${coordinate[0]}, ${coordinate[1]})`);

// Array of objects
const students: { name: string; grade: number }[] = [
  { name: "Alice", grade: 95 },
  { name: "Bob", grade: 87 },
  { name: "Charlie", grade: 92 }
];

console.log("\nStudents:");
students.forEach(student => {
  console.log(`${student.name}: ${student.grade}`);
});

// Find highest grade
const highest = students.reduce((max, student) =>
  student.grade > max.grade ? student : max
);
console.log(`Highest grade: ${highest.name} with ${highest.grade}`);

// Map
const phoneBook = new Map<string, string>();
phoneBook.set("Alice", "555-1234");
phoneBook.set("Bob", "555-5678");

console.log("\nPhone book:");
phoneBook.forEach((number, name) => {
  console.log(`${name}: ${number}`);
});

// Set
const tags = new Set<string>();
tags.add("typescript");
tags.add("javascript");
tags.add("programming");
tags.add("typescript"); // Duplicate, won't be added

console.log(`\nUnique tags (${tags.size}):`);
tags.forEach(tag => {
  console.log(`- ${tag}`);
});

Try these exercises:

  1. Create an array of numbers and find the average
  2. Create an interface for a Car with properties like make, model, and year
  3. Use map() to convert an array of Celsius temperatures to Fahrenheit
  4. Create a tuple representing RGB color values
  5. Use a Map to store and retrieve shopping cart items
  6. Create a Set to remove duplicates from an array

Key Takeaways

  • Arrays store ordered collections of the same type
  • Objects store key-value pairs for complex data
  • Use type aliases and interfaces to define object shapes
  • Tuples have fixed length and specific types for each position
  • Enums define named constants
  • Maps store key-value pairs with any key type
  • Sets store unique values only
  • Array methods like map, filter, and reduce are powerful tools

Pro Tip: Choose the right data structure for your needs. Arrays for ordered lists, objects for structured data, Maps for flexible key-value storage, and Sets for unique collections!

Next Steps

You've been using inline type annotations and basic interfaces to describe objects. Next, you'll dive deep into interfaces and type aliases — learning when to use each, how to extend them, and how intersection types let you compose complex shapes from simple ones.

Two-tier handoff: this document is the complete reading surface. Continue learning for stateful practice, progress, and real sandbox execution.