TypeScript Grundlagen

6 Kernkonzepte
Die wichtigsten TypeScript-Konzepte für die typisierte JavaScript-Entwicklung: Primitive Types · Interfaces · Type Aliases · Functions · Classes · Generics TypeScript erweitert JavaScript um statische Typen. Diese Konzepte sind essenziell für die Entwicklung skalierbarer, wartbarer und fehlerresistenter Anwendungen.

Primitive Types – string, number, boolean, etc.

string · number · boolean · null · undefined
let name: string = "Anna"; let age: number = 30; let isActive: boolean = true; let data: any = "beliebig";

Primitive Types sind die grundlegenden Datentypen in TypeScript. Sie helfen, Fehler frühzeitig zu erkennen und den Code besser zu dokumentieren.

Die wichtigsten primitiven Typen

Typ Beschreibung Beispiel
string Text (UTF-16) "Hallo Welt"
number Zahlen (Ganzzahlen & Fließkommazahlen) 42, 3.14, -5
boolean Wahrheitswerte true, false
null Absichtlich kein Wert null
undefined Nicht definierter Wert undefined
any Beliebiger Typ (deaktiviert Typ-Prüfung) "text", 123, true
unknown Beliebiger Typ (sicherer als any) "text", 123, true
void Kein Rückgabewert function() {}
Beispiele
// Typannotationen
let city: string = "Berlin";
let population: number = 3645000;
let isCapital: boolean = true;
// Typinferenz (TypeScript leitet den Typ ab)
let name = "Max"; // string
let count = 42; // number
// null und undefined
let value: string | null = null;
let optional: number | undefined;
Tipp: Verwenden Sie unknown statt any, wenn der Typ nicht bekannt ist – unknown erfordert eine Typ-Prüfung vor der Verwendung.

Interfaces – Strukturen definieren

interface · extends · optional · readonly
interface User { id: number; name: string; email?: string; // optional readonly createdAt: Date; }

Interfaces definieren die Struktur von Objekten. Sie beschreiben, welche Eigenschaften und Methoden ein Objekt haben muss – zur Kompilierzeit, nicht zur Laufzeit.

Beispiele
interface Person {
firstName: string;
lastName: string;
age: number;
getFullName?: () => string; // optionale Methode
}
// Erweiterung (extends)
interface Employee extends Person {
employeeId: number;
department: string;
}
// Verwendung
const user: Person = {
firstName: "Anna",
lastName: "Schmidt",
age: 30,
getFullName: () => `${this.firstName} ${this.lastName}`
};
Tipp: Interfaces werden zur Laufzeit entfernt – sie existieren nur während der Kompilierung. Verwenden Sie readonly für unveränderliche Eigenschaften.

Type Aliases – Typen benennen

type · Union · Intersection · Literal
type ID = string | number; type Status = "pending" | "done" | "failed"; type UserWithRole = User & { role: string };

Type Aliases erlauben die Benennung von beliebigen Typen – primitiven Typen, Unions, Intersections und komplexen Strukturen. Sie sind flexibler als Interfaces für manche Anwendungsfälle.

Beispiele
// Union Type (entweder oder)
type Result = string | number | boolean;
// Literal Type (feste Werte)
type Color = "red" | "green" | "blue";
// Intersection Type (Kombination)
type UserWithTimestamp = User & { createdAt: Date };
// Verwendung
let data: Result = "Hallo";
let color: Color = "red";
const user: UserWithTimestamp = {
id: 1,
name: "Anna",
createdAt: new Date()
};
Tipp: Verwenden Sie type für Union Types, Intersection Types und komplexe Typen. Verwenden Sie interface für Objektstrukturen, die erweitert werden sollen.

Functions – Typisierte Funktionen

(param: type) => returnType
function add(a: number, b: number): number { return a + b; } const greet = (name: string): string => `Hallo ${name}`;

Typisierte Funktionen definieren, welche Typen Parameter haben und welchen Rückgabetyp die Funktion liefert. Das verbessert die Code-Qualität und Dokumentation.

Beispiele
// Funktion mit Typannotation
function multiply(a: number, b: number): number {
return a * b;
}
// Arrow Function
const divide = (a: number, b: number): number => a / b;
// Optionale Parameter
function greet(name: string, title?: string): string {
return title ? `Hallo ${title} ${name}` : `Hallo ${name}`;
}
// Default Parameter
function pow(base: number, exponent: number = 2): number {
return Math.pow(base, exponent);
}
// Funktion als Typ
type Calculator = (a: number, b: number) => number;
const addFn: Calculator = (a, b) => a + b;
Tipp: TypeScript leitet den Rückgabetyp oft automatisch ab. Sie können ihn dennoch explizit angeben, um die Absicht zu dokumentieren.

Classes – Objekte und Vererbung

class · constructor · extends · implements
class Animal { constructor(public name: string) {} speak(): void { console.log(`${this.name} macht ein Geräusch`); } } class Dog extends Animal { speak(): void { console.log(`${this.name} bellt`); } }

Classes in TypeScript erweitern JavaScript-Klassen um Typannotationen, Sichtbarkeitsmodifikatoren (public, private, protected) und die Implementierung von Interfaces.

Beispiele
class Vehicle {
private _speed: number = 0;
constructor(public brand: string, public model: string) {}
accelerate(speed: number): void {
this._speed += speed;
console.log(`${this.brand} ${this.model} fährt mit ${this._speed} km/h`);
}
get speed(): number { return this._speed; }
}
// Vererbung
class Car extends Vehicle {
constructor(brand: string, model: string, public doors: number) {
super(brand, model);
}
honk(): void { console.log("Hup hup!"); }
}
// Verwendung
const car = new Car("Tesla", "Model 3", 4);
car.accelerate(50);
car.honk();
console.log(`Aktuelle Geschwindigkeit: ${car.speed} km/h`);
Tipp: Verwenden Sie private für Attribute, die nicht von außen geändert werden sollen, und protected für Vererbung. public ist der Standard.

Generics – Typen flexibel machen

<T> · <T, U> · extends
function identity<T>(value: T): T { return value; } const result = identity<string>("Hallo");

Generics ermöglichen die Erstellung von wiederverwendbaren Komponenten, die mit verschiedenen Typen arbeiten können. Sie bieten Typsicherheit bei maximaler Flexibilität.

Beispiele
// Generic Funktion
function wrapInArray<T>(value: T): T[] {
return [value];
}
const numbers = wrapInArray<number>(42); // number[]
const strings = wrapInArray("Hallo"); // string[] (Typinferenz)
// Generic Interface
interface Box<T> {
value: T;
label: string;
}
const box: Box<number> = { value: 100, label: "Punktestand" };
// Generic Class
class Stack<T> {
private items: T[] = [];
push(item: T): void { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
peek(): T | undefined { return this.items[this.items.length - 1]; }
}
const numberStack = new Stack<number>();
numberStack.push(10);
numberStack.push(20);
console.log(numberStack.pop()); // 20
// Generic Constraints
interface HasLength { length: number; }
function logLength<T extends HasLength>(item: T): void {
console.log(`Länge: ${item.length}`);
}
logLength("Hallo"); // Länge: 5
logLength([1, 2, 3]); // Länge: 3
Tipp: Generics werden zur Laufzeit entfernt – sie existieren nur zur Kompilierzeit. Sie helfen, redundanten Code zu vermeiden und die Typsicherheit zu erhöhen.

TypeScript im Überblick

tsc TypeScript Compiler
tsc file.ts → file.js
type Type Aliases
Union, Intersection, Literal
interface Strukturen definieren
extends, optional, readonly
<T> Generics
Flexible Typen
strict Strikte Typprüfung
tsconfig.json
any Jeder Typ (Vorsicht!)
Lieber unknown verwenden

Quick Summary

string
Primitive Typen
interface
Strukturen
type
Typ-Aliase
() => {}
Funktionen
class
Klassen
<T>
Generics
function identity<T>(value: T): T { return value; } · interface User { id: number; name: string; }