TypeScript Interfaces - Objekt-Typen definieren
Interfaces sind das Herzstück von TypeScript für Objekt-Typisierung.
Was sind Interfaces?
Ein Interface definiert die Struktur eines Objekts:
interface User {
name: string
age: number
email: string
}
// Objekt muss exakt der Struktur entsprechen
const user: User = {
name: "Max",
age: 25,
email: "max@example.com"
}
Vorteile:
- ✅ Autovervollständigung
- ✅ Type-Checking
- ✅ Refactoring-sicher
- ✅ Selbstdokumentierend
Interface Basics
Einfaches Interface
interface Product {
id: number
name: string
price: number
inStock: boolean
}
function displayProduct(product: Product): void {
console.log(`${product.name}: ${product.price}€`)
}
const laptop: Product = {
id: 1,
name: "MacBook Pro",
price: 1999,
inStock: true
}
displayProduct(laptop)
Optional Properties
Mit ? sind Properties optional:
interface User {
name: string
age: number
email?: string // Optional!
phone?: string // Optional!
}
// Beide OK
const user1: User = { name: "Max", age: 25 }
const user2: User = { name: "Anna", age: 30, email: "anna@test.com" }
Readonly Properties
Mit readonly sind Properties unveränderlich:
interface Config {
readonly apiUrl: string
readonly timeout: number
retries: number // Normal, änderbar
}
const config: Config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
}
config.retries = 5 // ✅ OK
config.apiUrl = "https://other.com" // ❌ Error: readonly!
Function Properties
Interfaces können auch Funktionen enthalten:
Method Syntax
interface Calculator {
add(a: number, b: number): number
subtract(a: number, b: number): number
}
const calc: Calculator = {
add(a, b) {
return a + b
},
subtract(a, b) {
return a - b
}
}
Property Syntax
interface Calculator {
add: (a: number, b: number) => number
subtract: (a: number, b: number) => number
}
Beide Syntaxen sind OK, Method Syntax ist üblicher.
Index Signatures
Für Objekte mit dynamischen Keys:
interface StringMap {
[key: string]: string
}
const translations: StringMap = {
hello: "Hallo",
goodbye: "Auf Wiedersehen",
thanks: "Danke"
// Beliebig viele string: string Paare
}
translations.welcome = "Willkommen" // ✅ OK
translations.count = 42 // ❌ Error: value muss string sein
Index Signatures mit zusätzlichen Properties
interface Dictionary {
[key: string]: string | number
length: number // Muss kompatibel mit Index Signature sein
}
const dict: Dictionary = {
length: 2,
hello: "Hallo",
count: 42
}
Extending Interfaces
Interfaces können von anderen Interfaces erben:
interface Person {
name: string
age: number
}
interface Employee extends Person {
employeeId: number
department: string
}
const employee: Employee = {
name: "Max",
age: 25,
employeeId: 12345,
department: "IT"
}
Multiple Extends
interface Printable {
print(): void
}
interface Saveable {
save(): void
}
interface Document extends Printable, Saveable {
title: string
content: string
}
const doc: Document = {
title: "My Doc",
content: "...",
print() { console.log(this.title) },
save() { console.log("Saved!") }
}
Interface vs Type Alias
TypeScript hat auch Type Aliases:
// Interface
interface User {
name: string
age: number
}
// Type Alias
type User = {
name: string
age: number
}
Unterschiede
| Feature | Interface | Type Alias |
|---------|-----------|------------|
| Extending | extends | & (Intersection) |
| Merging | ✅ Ja | ❌ Nein |
| Union Types | ❌ Nein | ✅ Ja |
| Primitives | ❌ Nein | ✅ Ja |
| Tuples | ⚠️ Umständlich | ✅ Ja |
Declaration Merging
Interfaces mit gleichem Namen werden gemergt:
interface User {
name: string
}
interface User {
age: number
}
// Beide werden zusammengefügt
const user: User = {
name: "Max",
age: 25
}
Vorteil: Gut für Library-Erweiterungen!
Type Alias für komplexe Typen
// Union Types - nur mit Type Alias
type Status = "active" | "inactive" | "pending"
// Intersection Types
type Admin = User & {
permissions: string[]
}
// Primitive Aliases
type ID = string | number
// Tuples
type Point = [number, number]
Empfehlung
- Interfaces für Objekt-Strukturen (besonders wenn extending nötig)
- Type Aliases für Unions, Intersections, Tuples, Primitives
// ✅ Interface für Objekte
interface User {
id: number
name: string
}
interface Admin extends User {
permissions: string[]
}
// ✅ Type Alias für Unions
type Status = "active" | "inactive" | "pending"
// ✅ Type Alias für Intersections
type AdminUser = User & {
role: "admin"
}
// ✅ Type Alias für komplexe Typen
type ApiResponse<T> = {
data: T
status: number
error?: string
}Funktionen mit Interfaces
Call Signatures
Interface für Funktions-Typen:
interface MathOperation {
(a: number, b: number): number
}
const add: MathOperation = (a, b) => a + b
const multiply: MathOperation = (a, b) => a * b
Construct Signatures
Für Constructor-Funktionen:
interface PersonConstructor {
new (name: string, age: number): Person
}
interface Person {
name: string
age: number
}
class Employee implements Person {
constructor(public name: string, public age: number) {}
}
// PersonConstructor Type für die Klasse
const PersonClass: PersonConstructor = Employee
const person = new PersonClass("Max", 25)
Hybrid Types
Interfaces können beides sein - Objekt UND Funktion:
interface Counter {
(start: number): string // Callable
interval: number // Property
reset(): void // Method
}
function getCounter(): Counter {
const counter = (start: number) => {
return `Started at ${start}`
} as Counter
counter.interval = 1000
counter.reset = () => {
console.log("Reset!")
}
return counter
}
const c = getCounter()
c(10) // "Started at 10"
c.interval // 1000
c.reset() // "Reset!"
Interfaces für React Components
Sehr nützlich in React:
interface ButtonProps {
text: string
onClick: () => void
disabled?: boolean
variant?: "primary" | "secondary"
}
function Button({ text, onClick, disabled = false, variant = "primary" }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled} className={variant}>
{text}
</button>
)
}
// Usage mit Autovervollständigung
<Button text="Click me" onClick={() => console.log("Clicked")} />
📝 Quiz
Was ist der Hauptunterschied zwischen Interface und Type Alias?
Tipps & Tricks
Interface Naming Convention
// ❌ Kein 'I' Prefix (wie in C#)
interface IUser {
name: string
}
// ✅ Einfach den Namen
interface User {
name: string
}
// ✅ Beschreibende Namen für Props
interface UserCardProps {
user: User
onClick: () => void
}
Pick und Omit Utilities
interface User {
id: number
name: string
email: string
password: string
}
// Nur bestimmte Properties
type PublicUser = Pick<User, "id" | "name" | "email">
// Alle außer bestimmte
type UserWithoutPassword = Omit<User, "password">
Partial und Required
interface User {
name: string
age: number
email: string
}
// Alle Properties optional
type PartialUser = Partial<User>
// Alle Properties required
interface OptionalUser {
name?: string
age?: number
}
type RequiredUser = Required<OptionalUser>
Häufige Fehler
Fehler 1: Excess Property Checks ignorieren
❌ FALSCH:
interface User {
name: string
age: number
}
const user: User = {
name: "Max",
age: 25,
email: "max@test.com" // ❌ Error: excess property
}
✅ RICHTIG:
// Entweder email hinzufügen
interface User {
name: string
age: number
email?: string
}
// Oder nicht als User typen
const user = {
name: "Max",
age: 25,
email: "max@test.com"
}
Fehler 2: Readonly falsch verstehen
❌ FALSCH:
interface User {
readonly name: string
readonly hobbies: string[]
}
const user: User = {
name: "Max",
hobbies: ["gaming", "coding"]
}
user.hobbies.push("reading") // ✅ OK! Array ist änderbar
✅ RICHTIG:
interface User {
readonly name: string
readonly hobbies: readonly string[]
}
const user: User = {
name: "Max",
hobbies: ["gaming", "coding"]
}
user.hobbies.push("reading") // ❌ Error
Fehler 3: Interface vs Type Alias verwechseln
❌ FALSCH:
// Union Type mit Interface nicht möglich
interface Status extends "active" | "inactive" // ❌ Error
✅ RICHTIG:
// Union Type mit Type Alias
type Status = "active" | "inactive"
Zusammenfassung
Du hast gelernt:
- ✅ Interfaces definieren Objekt-Strukturen
- ✅ Optional Properties mit
? - ✅ Readonly Properties mit
readonly - ✅ Interfaces erweitern mit
extends - ✅ Index Signatures für dynamische Keys
- ✅ Declaration Merging bei Interfaces
- ✅ Interface vs Type Alias - wann was nutzen
Key Takeaways:
- Interfaces für Objekte, Type Aliases für Unions/Intersections
readonlymacht nur die Referenz unveränderlich, nicht den Inhalt- Excess Property Checks bei direkten Zuweisungen
- Utility Types wie Pick, Omit, Partial nutzen
Nächste Schritte
Als Nächstes lernst du:
- Classes in TypeScript
- Generics für wiederverwendbare Interfaces
- Advanced Types (Union, Intersection, etc.)
Viel Erfolg! 🚀
Gut gemacht! 🎉
Du hast "TypeScript Interfaces - Objekt-Typen definieren" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
TypeScript Classes - Objektorientierte Programmierung
Lerne Classes in TypeScript mit Access Modifiers, Constructors, Inheritance, Abstract Classes und mehr.
TypeScript Basic Types - Primitive Datentypen
Lerne die grundlegenden Datentypen in TypeScript kennen: string, number, boolean, arrays, tuples und mehr.
TypeScript Best Practices - Professioneller Code
Lerne die wichtigsten Best Practices für sauberen und wartbaren TypeScript Code. Naming, Patterns, Do's and Don'ts.