Generyczne interfejsy i aliasy typów
Definiowanie generycznych interfejsów i aliasów typów, dodawanie ograniczeń i wartości domyślnych oraz poznanie zastosowań każdego z nich
Generyczne interfejsy i aliasy typów to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 1 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 3 lekcji w sumie.
Wprowadzenie
Cel: Tworzyć struktury wielokrotnego użytku za pomocą generycznych interfejsów i aliasów typów. Należy dodawać ograniczenia i wartości domyślne oraz poznać kluczowe różnice.
Przegląd lekcji
Cel: Stosuj ustrukturyzowaną współbieżność za pomocą coroutineScope, zrozum propagowanie wyjątków i bezpiecznie używaj narzędzi do anulowania.
Najważniejsze idee
- coroutineScope czeka na wszystkie korutyny podrzędne; błąd anuluje korutyny siostrzane.
- launch natychmiast kończy się błędem w zakresie; async ujawnia błędy podczas wywołania await().
- withTimeout anuluje pracę po upływie określonego limitu.
- Opakuj zakresy w try/catch, aby obsługiwać wyjątki.
Generyczny interfejs
Generyczny interfejs zawiera parametr typu. Kod wywołujący podstawia konkretne typy, na przykład 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);Generyczny alias typu
Alias typu również może być generyczny i opisywać obiekty, funkcje, unie lub przecięcia.
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);Oczekiwanie zakresu
coroutineScope tworzy zakres podrzędny, który kończy działanie dopiero po zakończeniu wszystkich korutyn podrzędnych.
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")
}Błąd anuluje korutyny siostrzane
Jeśli jedna korutyna podrzędna zgłosi wyjątek, zakres anuluje korutyny siostrzane i ponownie zgłosi wyjątek do kodu wywołującego; użyj try/catch w miejscu wywołania.
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")
}Ograniczenia
Należy dodać ograniczenie extends, aby T udostępniał wymagane składowe, na przykład id, metodom interfejsu.
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));Błędy async i await
Wyjątki z async są zgłaszane podczas wywołania await(); obsłuż je za pomocą 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")
}Wartości domyślne i rozszerzanie
Należy podawać domyślne parametry typu dla wygody oraz budować na istniejących typach za pomocą typów pomocniczych, na przykład 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: readonlyAnulowanie za pomocą withTimeout
Użyj withTimeout, aby ograniczyć czas pracy; anuluje on korutynę podrzędną i zgłasza wyjątek TimeoutCancellationException.
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")
}
}Różnice w scalaniu
Interfejsy obsługują scalanie deklaracji. Aliasy typów nie mogą być scalane; powtórzone nazwy powodują błędy.
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)Zasada błędu w ustrukturyzowanej współbieżności
Sprawdzenie interfejsów a aliasów typów
Szybkie sprawdzenie: Które stwierdzenie dotyczące generycznych interfejsów i aliasów typów jest PRAWDZIWE?
Podsumowanie
Podsumowanie: Należy używać generycznych interfejsów i aliasów typów do modelowania struktur wielokrotnego użytku. Warto dodawać ograniczenia i wartości domyślne oraz pamiętać, że tylko interfejsy można scalać.
Podsumowanie
Podsumowanie: Używaj coroutineScope do grupowania pracy; błędna korutyna podrzędna anuluje korutyny siostrzane. Obsługuj błędy za pomocą try/catch, ujawniaj błędy async podczas wywołania await() i anuluj długotrwałe zadania za pomocą withTimeout.
Często zadawane pytania
Czy lekcja „Generyczne interfejsy i aliasy typów” jest bezpłatna?
Tak — pełny tekst „Generyczne interfejsy i aliasy typów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 3 lekcji w sumie.
Co nauczysz się w „Generyczne interfejsy i aliasy typów”?
Definiowanie generycznych interfejsów i aliasów typów, dodawanie ograniczeń i wartości domyślnych oraz poznanie zastosowań każdego z nich Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?
Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 3.
Ile czasu zajmuje lekcja „Generyczne interfejsy i aliasy typów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?
Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Generyczne interfejsy i aliasy typów
- Typy warunkowe — wprowadzenie — i dystrybucja po uniach
- Wielokrotnego użytku wzorce modeli danych