0Pricing
TypeScript Academy · Lekcja

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: readonly

Anulowanie 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

W coroutineScope, co się dzieje, gdy jedna korutyna podrzędna kończy działanie z wyjątkiem?

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

  1. Generyczne interfejsy i aliasy typów
  2. Typy warunkowe — wprowadzenie — i dystrybucja po uniach
  3. Wielokrotnego użytku wzorce modeli danych
← Powrót do TypeScript Academy