Skip to content

Kapitel 3: Fortgeschrittene Typen

🎯 Lernziele

In diesem Kapitel lernen Sie:

  • ✅ Union Types (|)
  • ✅ Intersection Types (&)
  • ✅ Type Aliases (type)
  • ✅ Literal Types
  • ✅ Optional Properties (?)
  • ✅ Non-Null Assertion (!)
  • ✅ Unknown Type
  • ✅ Type Guards (typeof, instanceof)

3.1 Union Types (|)

📖 Einfache Definition

Ein Union Type erlaubt einer Variable, mehrere Typen anzunehmen.

💻 Code-Beispiel

typescript
// Union Type
let value: string | number;

value = "Hallo";   // ✅ Erlaubt
value = 123;        // ✅ Erlaubt
value = true;       // ❌ Fehler: boolean ist nicht erlaubt

// Funktion mit Union Type
function formatId(id: string | number): string {
  return `ID: ${id}`;
}

console.log(formatId("abc"));  // Ausgabe: ID: abc
console.log(formatId(123));    // Ausgabe: ID: 123

🎨 Praxis-Beispiel

typescript
// Array mit gemischten Typen
let mixedArray: (string | number)[] = ["Hallo", 1, "Welt", 2];

// Typen einschränken
function processValue(value: string | number): void {
  if (typeof value === "string") {
    console.log(value.toUpperCase());  // TS weiß: value ist string
  } else {
    console.log(value.toFixed(2));    // TS weiß: value ist number
  }
}

3.2 Intersection Types (&)

📖 Einfache Definition

Ein Intersection Type kombiniert mehrere Typen zu einem einzigen Typ, der alle Eigenschaften der kombinierten Typen hat.

💻 Code-Beispiel

typescript
// Zwei Interfaces
interface Person {
  name: string;
  age: number;
}

interface Employee {
  employeeId: number;
  department: string;
}

// Intersection Type
type EmployeePerson = Person & Employee;

// Verwendung
const emp: EmployeePerson = {
  name: "Max",
  age: 25,
  employeeId: 12345,
  department: "IT"
};

🆚 Union vs Intersection

| Feature | Union (|) | Intersection (&) | |---------|-------------|-------------------| | Bedeutung | ODER (einer von beiden) | UND (beide kombiniert) | | Beispiel | string \| number | Person & Employee | | Werte | Eine von mehreren Typen | Alle Typen gleichzeitig |


3.3 Type Aliases (type)

📖 Einfache Definition

Ein Type Alias erstellt einen neuen Namen für einen Typ.

💻 Code-Beispiel

typescript
// Einfacher Type Alias
type StringOrNumber = string | number;

let value: StringOrNumber;
value = "Hallo";  // ✅
value = 123;       // ✅

// Type Alias für Objekt
type User = {
  id: number;
  name: string;
  email: string;
};

const user: User = {
  id: 1,
  name: "Max",
  email: "max@example.com"
};

// Type Alias für Funktion
type GreetFunction = (name: string) => string;

const greet: GreetFunction = (name) => `Hallo, ${name}!`;

💡 Vorteile von Type Aliases

typescript
// ✅ Wiederverwendbarkeit
type ID = string | number;

function getUserById(id: ID) { /* ... */ }
function deleteUserById(id: ID) { /* ... */ }

// ✅ Lesbarkeit
type UserRole = "admin" | "user" | "guest";

// ✅ Komplexe Typen vereinfachen
type ApiResponse<T> = {
  success: boolean;
  data: T;
  message?: string;
};

3.4 Literal Types

📖 Einfache Definition

Literal Types erlauben nur spezifische Werte, nicht alle Werte eines Typs.

💻 Code-Beispiel

typescript
// String Literal Type
type Direction = "north" | "south" | "east" | "west";

let dir: Direction;
dir = "north";   // ✅ Erlaubt
dir = "south";   // ✅ Erlaubt
dir = "up";      // ❌ Fehler

// Number Literal Type
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

let roll: DiceRoll;
roll = 3;  // ✅ Erlaubt
roll = 7;   // ❌ Fehler

// Boolean Literal Type
type TrueOnly = true;

let isActive: TrueOnly = true;   // ✅ Erlaubt
isActive = false;                  // ❌ Fehler

🎨 Praxis-Beispiel

typescript
// Status einer API-Anfrage
type ApiStatus = "idle" | "loading" | "success" | "error";

function handleApiStatus(status: ApiStatus): void {
  switch (status) {
    case "idle":
      console.log("Bereit");
      break;
    case "loading":
      console.log("Lädt...");
      break;
    case "success":
      console.log("Erfolgreich!");
      break;
    case "error":
      console.log("Fehler aufgetreten");
      break;
  }
}

3.5 Optional Properties (?)

📖 Einfache Definition

Optionale Eigenschaften müssen nicht zwingend vorhanden sein.

💻 Code-Beispiel

typescript
// Interface mit optionalen Eigenschaften
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 {
  // ❌ Falsch: age könnte undefined sein
  console.log(user.age.toFixed(2));  // Fehler!

  // ✅ Richtig: Prüfen, ob age existiert
  if (user.age !== undefined) {
    console.log(user.age.toFixed(2));
  }

  // ✅ Richtig: Optional Chaining
  console.log(user.age?.toFixed(2));
}

3.6 Non-Null Assertion (!)

📖 Einfache Definition

Der Non-Null Assertion Operator (!) teilt dem Compiler, dass ein Wert nicht null oder undefined ist.

💻 Code-Beispiel

typescript
// Ohne Non-Null Assertion
function getElement(id: string): HTMLElement | null {
  return document.getElementById(id);
}

const el1 = getElement("myDiv");
// ❌ Fehler: el1 könnte null sein
el1.innerHTML = "Hallo";

// ✅ Mit Non-Null Assertion (Vorsicht!)
const el2 = getElement("myDiv")!;
el2.innerHTML = "Hallo";  // OK (aber gefährlich!)

⚠️ Warnung

typescript
// ❌ Gefährlich: Non-Null Assertion missbrauchen
function getValue(): string | undefined {
  return undefined;
}

const value = getValue()!;  // Erzwingt Typumwandlung
console.log(value.length);   // Laufzeitfehler: Cannot read property 'length' of undefined

// ✅ Sicherer: Type Guard verwenden
const value2 = getValue();
if (value2 !== undefined) {
  console.log(value2.length);  // Sicher!
}

3.7 Unknown Type (Sichere Alternative zu any)

📖 Einfache Definition

unknown ist wie any, aber typsicherer. Sie können nicht direkt Operationen auf einem unknown Wert ausführen.

💻 Code-Beispiel

typescript
// Any (Unsicher)
let anyValue: any = "Hallo";
anyValue.foo.bar();  // Keine Fehlermeldung zur Kompilierungszeit!

// Unknown (Sicherer)
let unknownValue: unknown = "Hallo";
unknownValue.foo.bar();  // ❌ Fehler: Object is of type 'unknown'

// ✅ Unknown muss zuerst überprüft werden
if (typeof unknownValue === "string") {
  console.log(unknownValue.toUpperCase());  // OK
}

🆚 Any vs Unknown

Featureanyunknown
TypsicherheitKeineVollständig
Direkter ZugriffErlaubtVerboten
Type Guards erforderlichNeinJa
EmpfehlungVermeidenVerwenden statt any

3.8 Type Guards

📖 Einfache Definition

Type Guards sind Techniken, um den Typ einer Variable zur Laufzeit einzuschränken.

💻 Code-Beispiel

typeof Type Guard

typescript
function processValue(value: string | number): void {
  if (typeof value === "string") {
    // value ist hier string
    console.log(value.toUpperCase());
  } else {
    // value ist hier number
    console.log(value.toFixed(2));
  }
}

instanceof Type Guard

typescript
class Car {
  drive() {
    console.log("Fährt...");
  }
}

class Boat {
  sail() {
    console.log("Segelt...");
  }
}

function useVehicle(vehicle: Car | Boat): void {
  if (vehicle instanceof Car) {
    vehicle.drive();  // TS weiß: vehicle ist Car
  } else {
    vehicle.sail();   // TS weiß: vehicle ist Boat
  }
}

Custom Type Guard (is)

typescript
interface Fish {
  swim(): void;
}

interface Bird {
  fly(): void;
}

// Custom Type Guard
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

function move(pet: Fish | Bird): void {
  if (isFish(pet)) {
    pet.swim();  // TS weiß: pet ist Fish
  } else {
    pet.fly();   // TS weiß: pet ist Bird
  }
}

📝 Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • Union Types (|): Variable kann mehrere Typen annehmen
  • Intersection Types (&): Kombiniert mehrere Typen
  • Type Aliases (type): Erstellt neue Namen für Typen
  • Literal Types: Erlaubt nur spezifische Werte
  • Optional Properties (?): Eigenschaften sind nicht zwingend erforderlich
  • Non-Null Assertion (!): Erzwingt, dass Wert nicht null/undefined ist (Vorsicht!)
  • Unknown Type: Sicherere Alternative zu any
  • Type Guards: Schränkt Typen zur Laufzeit ein

🎯 Nächstes Kapitel

Im Kapitel 4 lernen wir Interfaces (Schnittstellen), das Herzstück von TypeScript!

👉 Weiter zu Kapitel 4: Interfaces


❓ Häufig gestellte Fragen

F: Wann sollte ich Union Types verwenden?

A: Wenn eine Variable mehrere, aber begrenzte Typen annehmen kann (z.B. string | number).

F: Was ist der Unterschied zwischen type und interface?

A: Beide können für Objekt-Typen verwendet werden. interface kann erweitert werden (extends), type ist flexibler (kann Union Types, Tuples, etc. definieren).

F: Ist unknown besser als any?

A: Ja! unknown zwingt Sie, den Typ zur Laufzeit zu überprüfen, was Laufzeitfehler verhindert.


🎉 Herzlichen Glückwunsch! Sie haben Kapitel 3 abgeschlossen!

Frei für alle Anfänger