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
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
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?
| Tool | Purpose |
|---|---|
interface | Describes ONLY the shape of data – no implementation, does NOT exist at runtime, only for type checking. Our Book/Author types: pure data containers. |
class | Bundles 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.