Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Class Basics in TypeScript

Class Basics

~16 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

So far, our interfaces have only described DATA – no BEHAVIOR. A Library class shouldn't just STORE the stock, it should also offer operations on it (borrow a book, return it, search). Classes are TypeScript's tool for that.

The first class: Library

src/services/Library.ts
import { Book } from '../models/Book.js';

export class Library {
  stock: Book[];

  constructor(initialStock: Book[]) {
    this.stock = initialStock;
  }

  bookCount(): number {
    return this.stock.length;
  }

  findByTitle(title: string): Book | undefined {
    return this.stock.find((book) => book.title === title);
  }
}

stock: Book[] is a PROPERTY – like an interface field, but inside a class. The constructor runs ONCE when you call new Library(...), and initializes the properties. Methods like bookCount() are functions that can access this (the current instance).

Using the class

src/index.ts
import { Library } from './services/Library.js';
import { libraryStock } from './data/sampleData.js';

const library = new Library([...libraryStock]);
// [...libraryStock] copies the readonly array (chapter 11) into a
// new, MUTABLE array - the Library class needs a regular Book[],
// not a readonly stock, since it will later add/remove books

console.log(`The library has ${library.bookCount()} books.`);

const found = library.findByTitle('1984');
if (found) {
  console.log(`Found: ${found.title} by ${found.author.name}`);
}

Constructor property promotion: less typing

The pattern "declare a property + assign it in the constructor" is so common that TypeScript offers a shortcut for it:

// Verbose (as above):
export class Library {
  stock: Book[];
  constructor(stock: Book[]) {
    this.stock = stock;
  }
}

// Short form with constructor property promotion - EXACTLY the same result:
export class Library {
  constructor(public stock: Book[]) {}
}

public stock: Book[] declared DIRECTLY in the constructor parameter declares the property AND assigns it automatically AT THE SAME TIME – no separate this.stock = stock needed anymore. public gets explained in detail in chapter 14 (access modifiers); for now, it's enough to know it enables the shorthand.

When a class, when an interface?

ToolPurpose
interfaceDescribes ONLY the shape of data – no implementation, does NOT exist at runtime, only for type checking. Our Book/Author types: pure data containers.
classBundles data AND behavior (methods) – ALSO exists at runtime as a real JavaScript construct, instantiable with new. Our Library: has operations that work on the data.

A common rule of thumb: pure DATA (what a book IS) as an interface, things with BEHAVIOR (what you can DO with a library) as a class. We'll follow this separation consistently throughout the rest of the tutorial – src/models/ for interfaces, src/services/ for classes.

Extending methods: implementing checkout

// Addition to Library.ts:
checkOut(isbn: string): boolean {
  const book = this.stock.find((b) => b.isbn === isbn);
  if (!book || book.status !== 'available') {
    return false;
  }
  book.status = 'borrowed';
  return true;
}

checkOut returns boolean to signal success/failure – a deliberately simple pattern for now; chapter 25 (error handling) shows a more expressive alternative with custom error types.

Tipp: From here on, our Library class keeps growing across several chapters – inheritance (chapter 13), access modifiers (chapter 14), and generics (chapters 17-18) ALL build directly on this foundation.