Generische Interfaces und Type Aliases
Definieren Sie generische Interfaces und Type Aliases, fügen Sie Constraints und Standardwerte hinzu und verstehen Sie, wofür sich die jeweiligen Varianten besonders eignen.
Generische Interfaces und Type Aliases ist eine kostenlose TypeScript Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 3. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des TypeScript Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der TypeScript Academy-Kurs umfasst insgesamt 3 Lektionen.
Einführung
Ziel: Erstellen Sie mit generischen Interfaces und Typaliasen wiederverwendbare Strukturen. Sie fügen Constraints und Standardwerte hinzu und lernen die wichtigsten Unterschiede kennen.
Lektionsübersicht
Ziel: Verwenden Sie strukturierte Nebenläufigkeit mit coroutineScope, verstehen Sie die Ausbreitung von Ausnahmen und verwenden Sie Werkzeuge zum sicheren Abbruch.
Wichtige Konzepte
- coroutineScope wartet auf alle Kind-Coroutines; ein Fehler bricht Geschwister ab.
- launch schlägt im Scope sofort fehl; async macht Fehler bei await() sichtbar.
- withTimeout bricht die Arbeit nach Ablauf eines Zeitlimits ab.
- Umschließen Sie Scopes mit try/catch, um Ausnahmen zu behandeln.
Generisches Interface
Ein generisches Interface enthält einen Typparameter. Aufrufer setzen konkrete Typen ein (z. B. Box<number>).
interface Box<T> {
value: T;
}
const nBox: Box<number> = { value: 42 };
const sBox: Box<string> = { value: "ts" };
console.log(nBox.value, sBox.value);Generischer Typalias
Auch ein Typalias kann generisch sein und Objekte, Funktionen, Unions oder Schnittmengen ausdrücken.
type Pair<A, B> = { first: A; second: B };
const p1: Pair<number, string> = { first: 1, second: "one" };
const p2: Pair<boolean, boolean> = { first: true, second: false };
console.log(p1, p2);Warteverhalten von Scopes
coroutineScope erstellt einen untergeordneten Scope, der erst abgeschlossen wird, nachdem seine Kinder beendet sind.
import kotlinx.coroutines.*
suspend fun doTwoTasks(): Unit = coroutineScope {
// Both run concurrently and the scope waits for them
launch { delay(150); println("Task A done") }
launch { delay(100); println("Task B done") }
// returning Unit implicitly after children complete
}
fun main() = runBlocking {
doTwoTasks()
println("Scope completed")
}Fehler bricht Geschwister ab
Wenn ein Kind eine Ausnahme auslöst, bricht der Scope Geschwister ab und gibt die Ausnahme an den Aufrufer weiter. Verwenden Sie try/catch am Aufrufort.
import kotlinx.coroutines.*
suspend fun failingGroup() = coroutineScope {
val a = launch {
try {
repeat(5) { i ->
println("A $i"); delay(60)
}
} finally {
println("A cancelled")
}
}
launch {
delay(120)
throw IllegalStateException("boom") // failure in child
}
a.join() // will be cancelled when sibling fails
}
fun main() = runBlocking {
try {
failingGroup()
} catch (e: Exception) {
println("Caught in caller: ${e.message}")
}
println("Caller continues")
}Constraints
Fügen Sie eine extends-Constraint hinzu, damit T die erforderlichen Member (z. B. id) für die Methoden des Interfaces bereitstellt.
interface Repository<T extends { id: number }> {
getById(id: number): T | undefined;
save(entity: T): void;
}
type User = { id: number; name: string };
const memRepo: Repository<User> = {
store: [] as User[],
getById(id) {
return this.store.find(u => u.id === id);
},
save(u) {
this.store.push(u);
}
} as unknown as Repository<User>;
memRepo.save({ id: 1, name: "Ada" });
console.log(memRepo.getById(1));Fehler bei async und await
Ausnahmen von async werden ausgelöst, wenn Sie await() aufrufen; behandeln Sie sie mit try/catch.
import kotlinx.coroutines.*
suspend fun parseAsync(s: String) = coroutineScope {
val deferred = async {
delay(50)
s.toInt() // may throw NumberFormatException
}
try {
println("Result = ${deferred.await()}") // error appears here
} catch (e: NumberFormatException) {
println("Handled parse error: ${e::class.simpleName}")
}
}
fun main() = runBlocking {
parseAsync("12")
parseAsync("xx")
}Standardwerte und Erweiterung
Legen Sie aus Gründen der Benutzerfreundlichkeit Standard-Typparameter fest und bauen Sie mit Utilities auf Typen auf (z. B. Readonly<Box<T>>).
interface ApiResponse<T = unknown> {
data: T;
ok: boolean;
}
type ReadonlyBox<T> = Readonly<Box<T>>;
const r1: ApiResponse = { data: "ok", ok: true }; // T defaults to unknown
const r2: ApiResponse<number> = { data: 200, ok: true };
const rb: ReadonlyBox<string> = { value: "fixed" };
// rb.value = "change"; // Error: readonlyAbbruch mit withTimeout
Verwenden Sie withTimeout, um den Arbeitsumfang zu begrenzen; es bricht das Kind ab und löst TimeoutCancellationException aus.
import kotlinx.coroutines.*
suspend fun slowOp(): Int {
delay(300) // pretend work
return 42
}
fun main() = runBlocking {
try {
val result = withTimeout(150) { slowOp() } // cancels after 150ms
println("Got $result")
} catch (e: TimeoutCancellationException) {
println("Timed out and cancelled")
}
}Unterschiede beim Zusammenführen
Interfaces unterstützen das Zusammenführen von Deklarationen. Typaliase können nicht zusammengeführt werden; doppelte Namen führen zu Fehlern.
interface Settings { theme: string }
interface Settings { lang: string }
// Merged: Settings has { theme: string; lang: string }
const s: Settings = { theme: "dark", lang: "en" };
// type Settings = { foo: string };
// Error: Duplicate identifier 'Settings' for type aliases (no merging)Fehlerregel der strukturierten Nebenläufigkeit
Prüfung: Interfaces vs. Typen
Kurzer Test: Welche Aussage über generische Interfaces und Typaliase ist RICHTIG?
Zusammenfassung
Zusammenfassung: Verwenden Sie generische Interfaces und Typaliase, um wiederverwendbare Strukturen zu modellieren. Fügen Sie Constraints und Standardwerte hinzu und denken Sie daran: Nur Interfaces lassen sich zusammenführen.
Zusammenfassung
Zusammenfassung: Verwenden Sie coroutineScope, um Arbeit zu gruppieren; ein fehlschlagendes Kind bricht Geschwister ab. Behandeln Sie Fehler mit try/catch, machen Sie async-Fehler bei await() sichtbar und brechen Sie lang laufende Aufgaben mit withTimeout ab.
Häufig gestellte Fragen
Ist die Lektion „Generische Interfaces und Type Aliases“ kostenlos?
Ja — der vollständige Text von „Generische Interfaces und Type Aliases“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des TypeScript Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der TypeScript Academy-Kurs umfasst insgesamt 3 Lektionen.
Was lerne ich in „Generische Interfaces und Type Aliases“?
Definieren Sie generische Interfaces und Type Aliases, fügen Sie Constraints und Standardwerte hinzu und verstehen Sie, wofür sich die jeweiligen Varianten besonders eignen. Du übst TypeScript Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um TypeScript Academy zu starten?
Keine Vorkenntnisse erforderlich. TypeScript Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 3.
Wie lange dauert die Lektion „Generische Interfaces und Type Aliases“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser TypeScript Academy-Lektion Code schreiben und ausführen?
Ja. Jede TypeScript Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Generische Interfaces und Type Aliases
- Bedingte Typen (Einführung) und Verteilung über Unions
- Wiederverwendbare Muster für Datenmodelle