TypeScript - bedingte Typen

Hallo, zukünftige TypeScript-Zauberer! Heute machen wir uns auf eine aufregende Reise in die Welt der bedingten Typen. Keine Sorge, wenn du neu im Programmieren bist – ich werde dein freundlicher Guide sein, und wir gehen das Schritt für Schritt durch. Am Ende dieser Lektion wirst du erstaunt sein, wie viel du gelernt hast!

TypeScript - Conditional Types

Grundlegende bedingte Typen

Lassen Sie mit den Grundlagen beginnen. Bedingte Typen in TypeScript sind wie Entscheidungen in deinem Code treffen. Stell dir vor, du bist in einem Eiscreme-Geschäft und musst zwischen Schokolade und Vanille entscheiden, je nachdem, ob es ein heißer Tag ist oder nicht. Das ist im Wesentlichen, was bedingte Typen in TypeScript tun!

Hier ist ein einfaches Beispiel:

type IceCreamChoice = boolean extends true ? "Chocolate" : "Vanilla";

In diesem Code sagen wir: "Wenn boolean (der true oder false darstellt) true sein kann, dann wähle Schokolade; sonst wähle Vanille."

Aber wartet, boolean kann immer true sein, oder? Lassen wir das praktischer machen:

type WeatherChoice<T> = T extends "Hot" ? "Ice Cream" : "Hot Chocolate";

let summerChoice: WeatherChoice<"Hot"> = "Ice Cream";
let winterChoice: WeatherChoice<"Cold"> = "Hot Chocolate";

Hier haben wir einen Typ WeatherChoice erstellt, der einen Typenparameter T annimmt. Wenn T Hot extends (oder entspricht), wählen wir "Ice Cream"; anderenfalls wählen wir "Hot Chocolate".

Generische bedingte Typen

Nun, lassen Sie uns eine Stufe höher gehen! Generische bedingte Typen erlauben es uns, unsere Typen flexibler und wiederverwendbar zu machen. Denke daran wie eine superflexible Eiscrememaschine, die verschiedene Geschmacksrichtungen herstellen kann, je nachdem, was du hineingibst.

type IsArray<T> = T extends any[] ? true : false;

type CheckString = IsArray<string>;  // false
type CheckNumberArray = IsArray<number[]>;  // true

In diesem Beispiel überprüft IsArray, ob der Eingabetyp T ein Array ist. Wenn ja, gibt er true zurück; anderenfalls gibt er false zurück.

Lassen wir etwas Komplexeres versuchen:

type ElementType<T> = T extends (infer U)[] ? U : never;

type StringArrayElement = ElementType<string[]>;  // string
type NumberArrayElement = ElementType<number[]>;  // number
type NotArrayElement = ElementType<number>;  // never

Hier extrahiert ElementType den Typ der Elemente in einem Array. Wenn T ein Array ist, inferiert er den Elementtyp U und gibt ihn zurück. Wenn T kein Array ist, gibt er never zurück (was bedeutet "dies sollte nie passieren").

Bedingte Typenbeschränkungen

Manchmal möchten wir einige Beschränkungen auf unsere Typen setzen. Es ist, als würde man sagen: "Du kannst nur Eiscreme haben, wenn du deine Gemüse gegessen hast!" Lassen wir uns anschauen, wie das in TypeScript funktioniert:

type NumberOperation<T extends number> = T extends 0 ? "Zero" : "Non-zero";

type ZeroCheck = NumberOperation<0>;  // "Zero"
type NonZeroCheck = NumberOperation<5>;  // "Non-zero"
type InvalidCheck = NumberOperation<"5">;  // Fehler: Typ '"5"' erfüllt nicht die Beschränkung 'number'.

In diesem Beispiel akzeptiert NumberOperation nur Typen, die number extenden. Es überprüft dann, ob die Zahl 0 ist oder nicht.

Inferenz innerhalb bedingter Typen

Last but not least, lassen wir über die Inferenz innerhalb bedingter Typen sprechen. Das ist wie eine superkluge Eiscrememaschine, die herausfinden kann, welchen Geschmack du basierend auf deiner Stimmung möchtest!

type Flatten<T> = T extends Array<infer U> ? U : T;

type FlattenedNumberArray = Flatten<number[]>;  // number
type FlattenedString = Flatten<string>;  // string

Hier überprüft Flatten, ob T ein Array ist. Wenn ja, inferiert er den Elementtyp U und gibt ihn zurück. Wenn nicht, gibt er T wie ist zurück.

Lassen wir etwas fortgeschritteneres versuchen:

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

function greet(name: string): string {
return `Hello, ${name}!`;
}

type GreetReturn = ReturnType<typeof greet>;  // string

In diesem Beispiel inferiert ReturnType den Rückgabewert eines Functions. Es überprüft, ob T ein Funktionstyp ist, und wenn ja, inferiert und gibt den Rückgabewert R zurück.

Schlussfolgerung

Glückwunsch! Du hast gerade deine ersten Schritte in die Welt der bedingten Typen in TypeScript gemacht. Erinnere dich daran, dass es wie das Fahrradfahren ist, es fühlt sich am Anfang vielleicht wackelig an, aber mit Übung wirst du schnell davonfliegen!

Hier ist eine schnelle Referenztabelle der Methoden, die wir behandelt haben:

Methode Beschreibung
Grundlegende bedingte Typen Erstellen von Typentscheidungen basierend auf Bedingungen
Generische bedingte Typen Erstellen flexibler, wiederverwendbarer bedingter Typen
Bedingte Typenbeschränkungen Setzen von Beschränkungen auf Eingabetypen
Inferenz innerhalb bedingter Typen Extrahieren und Inferieren von Typen innerhalb von Bedingungen

Weiter üben, bleibe neugierig, und bevor du es merkst, wirst du erstaunliche Dinge mit TypeScript erstellen. Frohes Coden, zukünftige TypeScript-Meister!

Credits: Image by storyset