Appearance
Kapitel 4: Interfaces
🎯 Lernziele
In diesem Kapitel lernen Sie:
- ✅ Was Interfaces sind und warum sie wichtig sind
- ✅ Objekt-Interfaces definieren
- ✅ Optionale und readonly Eigenschaften
- ✅ Index Signatures (beliebige Eigenschaften)
- ✅ Interface Vererbung
- ✅ Unterschied zwischen
interfaceundtype
4.1 Was ist ein Interface?
📖 Einfache Definition
Ein Interface definiert die Struktur eines Objekts (welche Eigenschaften und Methoden es haben sollte).
💡 Kernkonzept
Interface = Vertrag (Contract)
Ein Interface sagt: "Jedes Objekt, das dieses Interface implementiert, muss diese Eigenschaften und Methoden haben."
🎨 Visuelle Erklärung
┌─────────────────────────────┐
│ Interface Person │
├─────────────────────────────┤
│ + name: string │
│ + age: number │
│ + greet(): void │
└─────────────────────────────┘
↓
┌─────────────────────────────┐
│ Objekt user │
├─────────────────────────────┤
│ name = "Max" │
│ age = 25 │
│ greet() { ... } │
└─────────────────────────────┘4.2 Objekt-Interface definieren
💻 Code-Beispiel
typescript
// Interface definieren
interface Person {
name: string;
age: number;
email: string;
}
// Interface verwenden
const user: Person = {
name: "Max",
age: 25,
email: "max@example.com"
};❌ Häufige Fehler
typescript
interface Person {
name: string;
age: number;
}
// ❌ Fehler: Eigenschaft fehlt
const user1: Person = {
name: "Max"
};
// ❌ Fehler: Eigenschaft ist vom falschen Typ
const user2: Person = {
name: "Max",
age: "25" // string statt number!
};
// ❌ Fehler: Zusätzliche Eigenschaft (im Strict Mode)
const user3: Person = {
name: "Max",
age: 25,
email: "max@example.com" // Nicht in Interface definiert!
};✅ Zusätzliche Eigenschaften erlauben
typescript
// Methode 1: Index Signature (später behandelt)
interface Person {
name: string;
age: number;
[key: string]: any; // Erlaubt zusätzliche Eigenschaften
}
// Methode 2: Type Assertion verwenden
interface Person {
name: string;
age: number;
}
const user = {
name: "Max",
age: 25,
email: "max@example.com"
} as Person; // Nicht empfohlen!4.3 Optionale Eigenschaften (?)
💻 Code-Beispiel
typescript
interface User {
id: number;
name: string;
email?: string; // Optional
age?: number; // Optional
}
// Erlaubt
const user1: User = {
id: 1,
name: "Max"
};
// Auch erlaubt
const user2: User = {
id: 2,
name: "Maria",
email: "maria@example.com",
age: 30
};⚠️ Zugriff auf optionale Eigenschaften
typescript
interface User {
name: string;
age?: number;
}
function printAge(user: User): void {
// ❌ Fehler: age könnte undefined sein
console.log(user.age.toFixed(2));
// ✅ Richtig: Prüfen
if (user.age !== undefined) {
console.log(user.age.toFixed(2));
}
// ✅ Richtig: Optional Chaining
console.log(user.age?.toFixed(2));
}4.4 Readonly Eigenschaften (readonly)
💻 Code-Beispiel
typescript
interface User {
readonly id: number; // Kann nur einmal zugewiesen werden
name: string;
age?: number;
}
const user: User = {
id: 1,
name: "Max"
};
user.name = "Maria"; // ✅ Erlaubt
user.age = 30; // ✅ Erlaubt
user.id = 2; // ❌ Fehler: Cannot assign to 'id' because it is a read-only property🎨 Readonly Array
typescript
// Readonly Array
const numbers: readonly number[] = [1, 2, 3];
numbers.push(4); // ❌ Fehler
numbers[0] = 10; // ❌ Fehler
// Alternative: ReadonlyArray<T>
const numbers2: ReadonlyArray<number> = [1, 2, 3];4.5 Index Signatures (Beliebige Eigenschaften)
💻 Code-Beispiel
typescript
// Index Signature: Erlaubt beliebige Eigenschaften
interface StringDictionary {
[key: string]: string;
}
const dict: StringDictionary = {
"de": "Hallo",
"en": "Hello",
"es": "Hola"
};
// Auch dynamische Keys
dict["fr"] = "Bonjour";🎨 Praxis-Beispiel
typescript
// API-Konfiguration
interface Config {
apiUrl: string;
timeout: number;
[key: string]: any; // Erlaubt zusätzliche Konfigurationen
}
const config: Config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3, // Zusätzlich
logLevel: "debug" // Zusätzlich
};4.6 Interface Vererbung (extends)
💻 Code-Beispiel
typescript
// Basis-Interface
interface Person {
name: string;
age: number;
}
// Abgeleitetes Interface
interface Employee extends Person {
employeeId: number;
department: string;
}
// Verwendung
const emp: Employee = {
name: "Max",
age: 25,
employeeId: 12345,
department: "IT"
};🎨 Mehrfach-Vererbung
typescript
interface CanFly {
fly(): void;
}
interface CanSwim {
swim(): void;
}
// Interface mit mehreren Eltern-Interfaces
interface Duck extends CanFly, CanSwim {
name: string;
}
const donald: Duck = {
name: "Donald",
fly() { console.log("Fliegt..."); },
swim() { console.log("Schwimmt..."); }
};4.7 Interface vs Type Alias
📊 Vergleich
| Feature | interface | type |
|---|---|---|
| Objekt-Typen | ✅ | ✅ |
| Vererbung | extends | & (Intersection) |
| Union Types | ❌ | ✅ |
| Primitive Typen | ❌ | ✅ |
| Declaration Merging | ✅ (automatisch) | ❌ |
💻 Code-Beispiel
typescript
// Interface: Vererbung
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
// Type Alias: Intersection
type Animal = {
name: string;
};
type Dog = Animal & {
breed: string;
};
// Type Alias: Union Type (Interface kann das nicht)
type Status = "pending" | "success" | "error";
// Type Alias: Primitive Typen (Interface kann das nicht)
type ID = string | number;💡 Empfehlung
- Verwenden Sie
interfacefür: Objekt-Typen, die erweitert werden können - Verwenden Sie
typefür: Union Types, Primitive Typen, Tuples, komplexe Typ-Kombinationen
4.8 Interface für Funktionen und Arrays
💻 Interface für Funktionen
typescript
// Interface für Funktionen
interface GreetFunction {
(name: string): string;
}
const greet: GreetFunction = (name) => `Hallo, ${name}!`;
console.log(greet("Max")); // Ausgabe: Hallo, Max!💻 Interface für Arrays
typescript
// Interface für Arrays
interface StringArray {
[index: number]: string;
}
const arr: StringArray = ["a", "b", "c"];
console.log(arr[0]); // Ausgabe: a4.9 Praxis: Datenstrukturen mit Interfaces definieren
💻 Vollständiges Beispiel
typescript
// API Response Interface
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
error?: string;
}
// User Interface
interface User {
id: number;
name: string;
email: string;
age?: number;
readonly createdAt: Date;
}
// API Response mit User-Daten
const response: ApiResponse<User> = {
success: true,
data: {
id: 1,
name: "Max",
email: "max@example.com",
createdAt: new Date()
},
message: "Benutzer erfolgreich abgerufen"
};
console.log(response.data.name); // Ausgabe: Max📝 Zusammenfassung
In diesem Kapitel haben Sie gelernt:
- ✅ Interface definiert die Struktur eines Objekts
- ✅ Optionale Eigenschaften (
?): Müssen nicht vorhanden sein - ✅ Readonly Eigenschaften (
readonly): Können nicht geändert werden - ✅ Index Signatures (
[key: string]: any): Erlauben beliebige Eigenschaften - ✅ Interface Vererbung (
extends): Erweitert bestehende Interfaces - ✅ Interface vs Type: Wann welches verwenden?
🎯 Nächstes Kapitel
Im Kapitel 5 lernen wir Funktionstypen (Parameter, Rückgabewerte, Overloads, etc.).
👉 Weiter zu Kapitel 5: Funktionstypen
❓ Häufig gestellte Fragen
F: Soll ich interface oder type verwenden?
A: Für Objekt-Typen: interface (bessere Erweiterbarkeit). Für Union Types, Primitive Typen: type.
F: Kann ich ein Interface nachträglich ändern?
A: Ja! TypeScript unterstützt "Declaration Merging" bei Interfaces:
typescript
interface User {
name: string;
}
interface User { // Wird zusammengeführt!
age: number;
}
// User hat jetzt name UND ageF: Warum "readonly" verwenden?
A: Um unbeabsichtigte Änderungen zu verhindern (immutability).
🎉 Herzlichen Glückwunsch! Sie haben Kapitel 4 abgeschlossen!
