Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Typy parametrów i zwracanych wartości

Witaj ponownie w Parku Jurajskim! Po wielu wycieczkach po interfejsach i typach, Dr. Henry Wu zabierze nas dzisiaj do centrum operacyjnego parku, gdzie przyjrzymy się dokładniej typowaniu funkcji - czyli określaniu typów parametrów i zwracanych wartości. Jest to kluczowy element zapewnienia bezpieczeństwa i przewidywalności w naszym systemie zarządzania parkiem - podobnie jak ścisłe protokoły bezpieczeństwa są niezbędne dla sprawnego funkcjonowania Parku Jurajskiego.

Podstawy typowania funkcji

Określanie typów parametrów i zwracanych wartości to fundamentalny element TypeScript. Pozwala nam to jasno zdefiniować, jakie dane funkcja przyjmuje i co zwraca - tworząc wyraźny "kontrakt" dla tej funkcji.

1// Podstawowa funkcja z typowanymi parametrami i zwracaną wartością
2function obliczWymaganiaPokarmowe(
3  waga: number,
4  jestDrapieżnikiem: boolean,
5  wiek: number
6): number {
7  // Dinozaury drapieżne potrzebują więcej kalorii
8  const wspólczynnikDiety = jestDrapieżnikiem ? 0.05 : 0.03;
9
10  // Młode dinozaury potrzebują więcej kalorii na jednostkę masy
11  const współczynnikWieku = wiek < 5 ? 1.2 : 1.0;
12
13  // Dzienna ilość pokarmu w kilogramach
14  return waga * wspólczynnikDiety * współczynnikWieku;
15}
16
17// Użycie funkcji
18const dziennyPosiłekTRex = obliczWymaganiaPokarmowe(7500, true, 7);
19console.log(`Dzienna ilość pokarmu dla T-Rex: ${dziennyPosiłekTRex} kg`);
20
21const dziennyPosiłekBrachiosaurus = obliczWymaganiaPokarmowe(35000, false, 22);
22console.log(`Dzienna ilość pokarmu dla Brachiosaurusa: ${dziennyPosiłekBrachiosaurus} kg`);

Funkcja powyżej jasno definiuje, że przyjmuje trzy parametry:

waga
(number),
jestDrapieżnikiem
(boolean) i
wiek
(number), a zwraca wartość typu
number
. Dzięki temu IDE i kompilator TypeScript będą w stanie wychwycić potencjalne błędy, takie jak próba wywołania funkcji z nieprawidłowymi typami argumentów.

Parametry opcjonalne i domyślne

W Parku Jurajskim, niektóre procedury mają parametry opcjonalne lub domyślne wartości. Na przykład, gdy zlecamy badanie dinozaura, możemy określić poziom priorytetowości, ale jeśli tego nie zrobimy, przyjmowana jest standardowa wartość.

1// Funkcja z parametrem opcjonalnym
2function zaplanujBadanieDinozaura(
3  id: string,
4  typ: "rutynowe" | "specjalistyczne",
5  priorytet?: 1 | 2 | 3 // Opcjonalny parametr
6): string {
7  // Jeśli priorytet nie został określony, używamy domyślnej wartości
8  const faktycznyPriorytet = priorytet || 2;
9
10  // Określamy termin badania na podstawie priorytetu
11  let terminWDniach: number;
12  switch (faktycznyPriorytet) {
13    case 1: terminWDniach = 1; break;   // Nagły przypadek - następny dzień
14    case 2: terminWDniach = 7; break;   // Standardowy priorytet - tydzień
15    case 3: terminWDniach = 30; break;  // Niski priorytet - miesiąc
16    default: terminWDniach = 7;
17  }
18
19  // Obliczamy datę badania
20  const dataBadania = new Date();
21  dataBadania.setDate(dataBadania.getDate() + terminWDniach);
22
23  return `Badanie ${typ} dla dinozaura ${id} zaplanowane na ${dataBadania.toLocaleDateString()} (priorytet: ${faktycznyPriorytet})`;
24}
25
26// Wywołanie z wszystkimi parametrami
27console.log(zaplanujBadanieDinozaura("TREX-01", "specjalistyczne", 1));
28
29// Wywołanie bez parametru opcjonalnego
30console.log(zaplanujBadanieDinozaura("STEG-03", "rutynowe"));
31
32// Alternatywnie, można użyć parametru z wartością domyślną
33function zaplanujBadanieDinozaura2(
34  id: string,
35  typ: "rutynowe" | "specjalistyczne",
36  priorytet: 1 | 2 | 3 = 2 // Parametr z wartością domyślną
37): string {
38  // Reszta implementacji jak wyżej...
39  const dataBadania = new Date();
40  dataBadania.setDate(dataBadania.getDate() + (priorytet === 1 ? 1 : priorytet === 2 ? 7 : 30));
41
42  return `Badanie ${typ} dla dinozaura ${id} zaplanowane na ${dataBadania.toLocaleDateString()} (priorytet: ${priorytet})`;
43}
44
45// Wywołanie bez podania parametru z wartością domyślną
46console.log(zaplanujBadanieDinozaura2("TRIC-02", "rutynowe"));

Zauważ różnicę między parametrem opcjonalnym (oznaczanym przez

?
) a parametrem z wartością domyślną (określanym przez
= wartość
). W obu przypadkach możemy pominąć ten parametr przy wywołaniu funkcji, ale podejście z wartością domyślną jest bardziej eleganckie i czytelne.

Typy zwracanych wartości

W typowaniu funkcji równie ważne jak typy parametrów są typy zwracanych wartości. TypeScript pozwala na precyzyjne określenie, co dokładnie funkcja zwraca, co pomaga w wykrywaniu potencjalnych błędów.

1// Funkcja zwracająca liczbę
2function obliczPojemnośćWybiegu(
3  długość: number,
4  szerokość: number,
5  typDinozaura: "mały" | "średni" | "duży"
6): number {
7  const powierzchnia = długość * szerokość;
8
9  // Ile dinozaurów danego typu można bezpiecznie umieścić na danej powierzchni
10  switch (typDinozaura) {
11    case "mały": return Math.floor(powierzchnia / 50);
12    case "średni": return Math.floor(powierzchnia / 200);
13    case "duży": return Math.floor(powierzchnia / 1000);
14    default: return 0;
15  }
16}
17
18// Funkcja zwracająca string
19function generujIdentyfikatorDinozaura(
20  gatunek: string,
21  numer: number
22): string {
23  // Tworzymy identyfikator na podstawie pierwszych 4 liter gatunku i numeru
24  const prefiks = gatunek.slice(0, 4).toUpperCase();
25  // Formatujemy numer jako 3-cyfrowy z wiodącymi zerami
26  const numerSformatowany = numer.toString().padStart(3, '0');
27
28  return `${prefiks}-${numerSformatowany}`;
29}
30
31// Funkcja zwracająca boolean
32function czyWybiegBezpieczny(
33  poziomBezpieczeństwa: number,
34  wymaganyPoziom: number,
35  ostatniPrzegląd: Date
36): boolean {
37  // Sprawdzamy, czy poziom bezpieczeństwa jest wystarczający
38  if (poziomBezpieczeństwa < wymaganyPoziom) {
39    return false;
40  }
41
42  // Sprawdzamy, czy przegląd był w ciągu ostatnich 30 dni
43  const dzisiaj = new Date();
44  const trzydzieściDniTemu = new Date(dzisiaj);
45  trzydzieściDniTemu.setDate(dzisiaj.getDate() - 30);
46
47  return ostatniPrzegląd >= trzydzieściDniTemu;
48}
49
50// Przykłady użycia
51const pojemnośćWybiegRaptorów = obliczPojemnośćWybiegu(100, 50, "średni");
52console.log(`Wybieg raptorów może pomieścić ${pojemnośćWybiegRaptorów} osobników`);
53
54const idNowegoDinozaura = generujIdentyfikatorDinozaura("Velociraptor", 42);
55console.log(`Nowy raptor otrzymał ID: ${idNowegoDinozaura}`);
56
57const statusWybiegTRex = czyWybiegBezpieczny(
58  5, // aktualny poziom
59  5, // wymagany poziom
60  new Date(2023, 4, 15) // data ostatniego przeglądu (15 maja 2023)
61);
62console.log(`Status bezpieczeństwa wybiegu T-Rex: ${statusWybiegTRex ? "BEZPIECZNY" : "WYMAGA UWAGI"}`);

Funkcje zwracające void

Niektóre funkcje nie zwracają wartości - są wywoływane głównie dla ich efektów ubocznych, takich jak modyfikacja stanu systemu, wyświetlanie informacji czy zapisywanie danych. W TypeScript taki przypadek oznaczamy typem zwracanej wartości

void
.

1// Funkcja nie zwracająca wartości (void)
2function zarejestrujZmianyOgrodzenia(
3  idWybiegu: string,
4  napięcie: number,
5  dataZmiany: Date = new Date() // Domyślnie używamy aktualnej daty
6): void {
7  // Zapisujemy informację o zmianie napięcia w ogrodzeniu
8  console.log(`[${dataZmiany.toISOString()}] Zmieniono napięcie w ogrodzeniu wybiegu ${idWybiegu} na ${napięcie}V`);
9
10  // W rzeczywistej aplikacji zapisalibyśmy te dane w bazie
11  // Funkcja nie zwraca żadnej wartości
12}
13
14// Wywołanie funkcji void
15zarejestrujZmianyOgrodzenia("TRX-PADDOCK", 10000);

Funkcje zwracające różne typy (union types)

W niektórych przypadkach funkcja może zwracać różne typy wartości w zależności od warunków lub parametrów. W TypeScript możemy to określić za pomocą union types.

1// Funkcja zwracająca różne typy wartości
2function pobierzDaneDinozaura(
3  id: string,
4  formatDanych: "podsumowanie" | "pełny" | "JSON"
5): string | object | null {
6  // Symulacja bazy danych
7  const bazaDanych: Record<string, {
8    nazwa: string;
9    gatunek: string;
10    wiek: number;
11    waga: number;
12    statusZdrowia: string;
13  }> = {
14    "TREX-001": {
15      nazwa: "Rexy",
16      gatunek: "Tyrannosaurus Rex",
17      wiek: 7,
18      waga: 8000,
19      statusZdrowia: "dobry"
20    },
21    "VEL-001": {
22      nazwa: "Blue",
23      gatunek: "Velociraptor",
24      wiek: 4,
25      waga: 160,
26      statusZdrowia: "doskonały"
27    }
28  };
29
30  // Sprawdzamy, czy dinozaur istnieje
31  if (!bazaDanych[id]) {
32    console.error(`Nie znaleziono dinozaura o ID ${id}`);
33    return null;
34  }
35
36  const dino = bazaDanych[id];
37
38  // Zwracamy różne formaty w zależności od parametru
39  switch (formatDanych) {
40    case "podsumowanie":
41      return `${dino.nazwa} (${dino.gatunek}): ${dino.statusZdrowia}`;
42
43    case "pełny":
44      return `
45        ID: ${id}
46        Nazwa: ${dino.nazwa}
47        Gatunek: ${dino.gatunek}
48        Wiek: ${dino.wiek} lat
49        Waga: ${dino.waga} kg
50        Status zdrowia: ${dino.statusZdrowia}
51      `;
52
53    case "JSON":
54      return { id, ...dino };
55
56    default:
57      return null;
58  }
59}
60
61// Przykłady użycia
62const podsumowanieRexy = pobierzDaneDinozaura("TREX-001", "podsumowanie");
63console.log(podsumowanieRexy);
64
65const pełneDaneBlue = pobierzDaneDinozaura("VEL-001", "pełny");
66console.log(pełneDaneBlue);
67
68const jsonDaneRexy = pobierzDaneDinozaura("TREX-001", "JSON") as object;
69console.log(JSON.stringify(jsonDaneRexy, null, 2));
70
71// Obsługa błędnych danych
72const nieistniejącyDinozaur = pobierzDaneDinozaura("INDOMINUS-001", "podsumowanie");
73if (nieistniejącyDinozaur === null) {
74  console.log("Nie znaleziono dinozaura");
75}

Funkcja

pobierzDaneDinozaura
zwraca string, object lub null w zależności od parametrów i warunków. Dzięki union types TypeScript wie, że wynik może być jednym z tych trzech typów i odpowiednio weryfikuje kod, który używa tej funkcji.

Typ funkcji (Function Types)

TypeScript umożliwia również definiowanie typów samych funkcji, co jest niezwykle przydatne przy przekazywaniu funkcji jako parametrów lub przypisywaniu ich do zmiennych.

1// Definicja typu funkcji
2type FunkcjaAlarmowa = (
3  poziomZagrożenia: number,
4  lokalizacja: string,
5  komunikat: string
6) => void;
7
8// Funkcja używająca funkcji jako parametru
9function uruchomProceduręBezpieczeństwa(
10  idWybiegu: string,
11  poziomZagrożenia: number,
12  funkcjaAlarmowa: FunkcjaAlarmowa
13): void {
14  console.log(`Uruchamianie procedury bezpieczeństwa dla wybiegu ${idWybiegu}`);
15
16  // Zamykanie bram
17  console.log(`- Zamykanie bram wybiegu ${idWybiegu}`);
18
19  // Aktywacja dodatkowych zabezpieczeń
20  if (poziomZagrożenia >= 4) {
21    console.log("- Aktywacja dodatkowego ogrodzenia elektrycznego");
22    console.log("- Wysłanie personelu bezpieczeństwa");
23  }
24
25  // Wywołanie przekazanej funkcji alarmowej
26  funkcjaAlarmowa(
27    poziomZagrożenia,
28    `Wybieg ${idWybiegu}`,
29    `Uruchomiono procedurę bezpieczeństwa poziomu ${poziomZagrożenia}`
30  );
31}
32
33// Implementacja funkcji alarmowej
34const alertDlaCentrumKontroli: FunkcjaAlarmowa = (poziom, lokalizacja, komunikat) => {
35  console.log("=== ALERT DLA CENTRUM KONTROLI ===");
36  console.log(`Poziom zagrożenia: ${poziom}`);
37  console.log(`Lokalizacja: ${lokalizacja}`);
38  console.log(`Komunikat: ${komunikat}`);
39  console.log("===================================");
40};
41
42// Alternatywna funkcja alarmowa
43const alertDlaPersoneluParku: FunkcjaAlarmowa = (poziom, lokalizacja, komunikat) => {
44  const priorytet = poziom >= 4 ? "KRYTYCZNY" : poziom >= 2 ? "WAŻNY" : "INFORMACYJNY";
45  console.log(`[${priorytet}] ${komunikat} w ${lokalizacja}`);
46
47  // W rzeczywistej aplikacji wysłalibyśmy tutaj powiadomienia do personelu
48};
49
50// Użycie funkcji z różnymi implementacjami funkcji alarmowej
51uruchomProceduręBezpieczeństwa("RAPTOR-01", 3, alertDlaCentrumKontroli);
52uruchomProceduręBezpieczeństwa("TREX-01", 5, alertDlaPersoneluParku);

W powyższym przykładzie zdefiniowaliśmy typ funkcji

FunkcjaAlarmowa
, który określa sygnaturę funkcji przyjmującej trzy parametry i nie zwracającej wartości. Następnie użyliśmy tego typu, aby zdefiniować parametr w funkcji
uruchomProceduręBezpieczeństwa
i implementacje konkretnych funkcji alarmowych.

Typowanie funkcji z callbackiem

Funkcje z callbackami są powszechne w JavaScript, szczególnie w operacjach asynchronicznych. TypeScript pozwala na precyzyjne typowanie takich funkcji.

1// Funkcja z callbackiem typowanym inline
2function monitorujZdrowieZwierzęcia(
3  idZwierzęcia: string,
4  interwałWSekundach: number,
5  callback: (dane: { temperatura: number; tętno: number; poziomStresu: number }) => void
6): void {
7  console.log(`Rozpoczęto monitoring zdrowia zwierzęcia ${idZwierzęcia} co ${interwałWSekundach} sekund`);
8
9  // Symulacja pierwszego pomiaru
10  const danePoczątkowe = {
11    temperatura: 38.5,
12    tętno: 72,
13    poziomStresu: 3
14  };
15
16  // Wywołanie callbacka z pierwszymi danymi
17  callback(danePoczątkowe);
18
19  // W rzeczywistej aplikacji ustawilibyśmy tutaj interwał do regularnego monitorowania
20  console.log("Monitoring uruchomiony");
21}
22
23// Użycie funkcji z callbackiem
24monitorujZdrowieZwierzęcia("TREX-001", 60, (dane) => {
25  console.log("Otrzymano nowe dane zdrowotne:");
26  console.log(`- Temperatura: ${dane.temperatura}°C`);
27  console.log(`- Tętno: ${dane.tętno} uderzeń/min`);
28  console.log(`- Poziom stresu: ${dane.poziomStresu}/10`);
29
30  // Sprawdzenie alertów zdrowotnych
31  if (dane.temperatura > 39.5) {
32    console.log("ALERT: Podwyższona temperatura!");
33  }
34
35  if (dane.tętno > 100) {
36    console.log("ALERT: Przyspieszone tętno!");
37  }
38
39  if (dane.poziomStresu > 7) {
40    console.log("ALERT: Wysoki poziom stresu!");
41  }
42});
43
44// Można również zdefiniować typ callbacka oddzielnie
45type CallbackMonitoringuZdrowia = (dane: {
46  temperatura: number;
47  tętno: number;
48  poziomStresu: number;
49  timeStamp?: Date; // opcjonalny parametr
50}) => void;
51
52// Funkcja z typem callbacka
53function zaawansowanyMonitoringZdrowia(
54  idZwierzęcia: string,
55  opcje: { interwał: number; powiadomienia: boolean },
56  callback: CallbackMonitoringuZdrowia
57): void {
58  console.log(`Konfiguracja zaawansowanego monitoringu dla ${idZwierzęcia}`);
59  console.log(`- Interwał: ${opcje.interwał} sekund`);
60  console.log(`- Powiadomienia: ${opcje.powiadomienia ? "włączone" : "wyłączone"}`);
61
62  // Symulacja danych z timestampem
63  const dane = {
64    temperatura: 38.2,
65    tętno: 68,
66    poziomStresu: 2,
67    timeStamp: new Date()
68  };
69
70  callback(dane);
71}
72
73// Użycie funkcji z typem callbacka
74zaawansowanyMonitoringZdrowia("STEG-003", { interwał: 120, powiadomienia: true }, (dane) => {
75  const czasPomiaru = dane.timeStamp ? dane.timeStamp.toISOString() : "nieznany";
76  console.log(`[${czasPomiaru}] Dane zdrowotne: T:${dane.temperatura}°C, HR:${dane.tętno}, Stres:${dane.poziomStresu}/10`);
77});

Funkcje generyczne

Jedną z najpotężniejszych funkcji TypeScript są generyki, które pozwalają na tworzenie funkcji i typów, które działają z różnymi typami danych, zachowując przy tym bezpieczeństwo typów.

1// Funkcja generyczna do filtrowania danych
2function filtrujDane<T>(
3  dane: T[],
4  predykat: (element: T) => boolean
5): T[] {
6  return dane.filter(predykat);
7}
8
9// Przykładowe dane dinozaurów
10interface DaneDino {
11  id: string;
12  nazwa: string;
13  gatunek: string;
14  waga: number;
15  poziomNiebezpieczeństwa: number;
16}
17
18const dinozaury: DaneDino[] = [
19  { id: "TREX-001", nazwa: "Rexy", gatunek: "T-Rex", waga: 8000, poziomNiebezpieczeństwa: 5 },
20  { id: "VEL-001", nazwa: "Blue", gatunek: "Velociraptor", waga: 150, poziomNiebezpieczeństwa: 4 },
21  { id: "TRIC-001", nazwa: "Tri", gatunek: "Triceratops", waga: 9000, poziomNiebezpieczeństwa: 2 },
22  { id: "STEG-001", nazwa: "Spike", gatunek: "Stegosaurus", waga: 5000, poziomNiebezpieczeństwa: 2 },
23  { id: "BRACH-001", nazwa: "Brachie", gatunek: "Brachiosaurus", waga: 40000, poziomNiebezpieczeństwa: 1 }
24];
25
26// Użycie generycznej funkcji z typem DaneDino
27const niebezpieczneDinozaury = filtrujDane<DaneDino>(
28  dinozaury,
29  dino => dino.poziomNiebezpieczeństwa >= 4
30);
31
32console.log("Niebezpieczne dinozaury:");
33niebezpieczneDinozaury.forEach(dino => {
34  console.log(`- ${dino.nazwa} (${dino.gatunek}): poziom zagrożenia ${dino.poziomNiebezpieczeństwa}`);
35});
36
37// Użycie tej samej funkcji z innym typem danych
38const temperatury = [28.5, 29.2, 30.1, 27.8, 31.5, 30.8, 32.1, 29.5];
39const wysokieTemperatury = filtrujDane<number>(
40  temperatury,
41  temp => temp > 30
42);
43
44console.log(`Zarejestrowano ${wysokieTemperatury.length} pomiarów z temperaturą powyżej 30°C`);
45
46// Bardziej złożona funkcja generyczna dla operacji na danych
47function przetwórzIZwróćDane<T, U>(
48  dane: T[],
49  transformacja: (element: T) => U
50): U[] {
51  return dane.map(transformacja);
52}
53
54// Użycie złożonej funkcji generycznej
55const raportDinozaurów = przetwórzIZwróćDane<DaneDino, { nazwa: string; poziomZagrożenia: string }>(
56  dinozaury,
57  dino => ({
58    nazwa: `${dino.nazwa} (${dino.gatunek})`,
59    poziomZagrożenia: dino.poziomNiebezpieczeństwa >= 4
60      ? "WYSOKI"
61      : dino.poziomNiebezpieczeństwa >= 3
62        ? "ŚREDNI"
63        : "NISKI"
64  })
65);
66
67console.log("Raport zagrożeń:");
68raportDinozaurów.forEach(raport => {
69  console.log(`- ${raport.nazwa}: ${raport.poziomZagrożenia}`);
70});

Funkcje generyczne są niezwykle elastyczne i pozwalają na wielokrotne wykorzystanie tej samej logiki z różnymi typami danych, przy jednoczesnym zachowaniu bezpieczeństwa typów.

Przeciążanie funkcji (Function Overloading)

TypeScript umożliwia przeciążanie funkcji, co pozwala na zdefiniowanie wielu sygnatur funkcji z różnymi typami parametrów i zwracanych wartości.

1// Przeciążenie funkcji dla różnych formatów ID
2// Definicje sygnatur funkcji
3function generujIdentyfikator(typ: "dinozaur", numer: number): string;
4function generujIdentyfikator(typ: "pracownik", imię: string, nazwisko: string): string;
5function generujIdentyfikator(typ: "lokalizacja", strefa: string, numer: number): string;
6
7// Implementacja funkcji obsługująca wszystkie przypadki
8function generujIdentyfikator(
9  typ: "dinozaur" | "pracownik" | "lokalizacja",
10  wartość1: number | string,
11  wartość2?: string
12): string {
13  switch (typ) {
14    case "dinozaur":
15      // wartość1 jest numerem
16      return `DINO-${(wartość1 as number).toString().padStart(3, '0')}`;
17
18    case "pracownik":
19      // wartość1 jest imieniem, wartość2 jest nazwiskiem
20      if (typeof wartość1 === "string" && typeof wartość2 === "string") {
21        const inicjały = `${wartość1.charAt(0)}${wartość2.charAt(0)}`.toUpperCase();
22        return `EMP-${inicjały}-${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`;
23      }
24      throw new Error("Nieprawidłowe parametry dla typu 'pracownik'");
25
26    case "lokalizacja":
27      // wartość1 jest strefą, wartość2 jest numerem
28      if (typeof wartość1 === "string" && typeof wartość2 === "number") {
29        return `LOC-${wartość1.toUpperCase()}-${wartość2.toString().padStart(2, '0')}`;
30      }
31      throw new Error("Nieprawidłowe parametry dla typu 'lokalizacja'");
32
33    default:
34      throw new Error(`Nieznany typ identyfikatora: ${typ}`);
35  }
36}
37
38// Przykłady użycia dla różnych przeciążeń
39const idDinozaura = generujIdentyfikator("dinozaur", 42);
40console.log(`ID dinozaura: ${idDinozaura}`);
41
42const idPracownika = generujIdentyfikator("pracownik", "John", "Hammond");
43console.log(`ID pracownika: ${idPracownika}`);
44
45const idLokalizacji = generujIdentyfikator("lokalizacja", "A", 5);
46console.log(`ID lokalizacji: ${idLokalizacji}`);

Przeciążanie funkcji pozwala na tworzenie bardziej elastycznych i czytelnych interfejsów API, gdzie ta sama funkcja może obsługiwać różne zestawy parametrów.

Typowanie funkcji asynchronicznych

W nowoczesnym JavaScript często używamy funkcji asynchronicznych. TypeScript doskonale współpracuje z obietnicami (Promises) i słowami kluczowymi

async/await
.

1// Funkcja asynchroniczna zwracająca Promise<string>
2async function pobierzDaneDinozauraZAPI(id: string): Promise<string> {
3  console.log(`Pobieranie danych dinozaura ${id} z API...`);
4
5  // Symulacja opóźnienia sieciowego
6  await new Promise(resolve => setTimeout(resolve, 1000));
7
8  // Symulacja danych z API
9  const dinozaury: Record<string, { nazwa: string; gatunek: string }> = {
10    "TREX-001": { nazwa: "Rexy", gatunek: "Tyrannosaurus Rex" },
11    "VEL-001": { nazwa: "Blue", gatunek: "Velociraptor" }
12  };
13
14  if (dinozaury[id]) {
15    const dino = dinozaury[id];
16    return `${dino.nazwa} (${dino.gatunek})`;
17  } else {
18    throw new Error(`Nie znaleziono dinozaura o ID ${id}`);
19  }
20}
21
22// Funkcja asynchroniczna zwracająca Promise<boolean>
23async function sprawdźStatusZdrowia(id: string): Promise<boolean> {
24  console.log(`Sprawdzanie statusu zdrowia dinozaura ${id}...`);
25
26  try {
27    // Symulacja opóźnienia
28    await new Promise(resolve => setTimeout(resolve, 800));
29
30    // Symulacja wyniku (dla uproszczenia zawsze zwraca true)
31    return true;
32  } catch (error) {
33    console.error(`Błąd podczas sprawdzania statusu zdrowia: ${error}`);
34    return false;
35  }
36}
37
38// Funkcja asynchroniczna używająca wielu operacji asynchronicznych
39async function przygotujRaportDinozaura(id: string): Promise<{
40  id: string;
41  dane: string;
42  statusZdrowia: boolean;
43  czasGenerowania: string;
44}> {
45  console.log(`Przygotowywanie raportu dla dinozaura ${id}...`);
46
47  // Równoległe wykonanie dwóch operacji asynchronicznych
48  const [dane, statusZdrowia] = await Promise.all([
49    pobierzDaneDinozauraZAPI(id),
50    sprawdźStatusZdrowia(id)
51  ]);
52
53  // Przygotowanie raportu
54  return {
55    id,
56    dane,
57    statusZdrowia,
58    czasGenerowania: new Date().toISOString()
59  };
60}
61
62// Użycie funkcji asynchronicznych
63async function przykładUżyciaAsync() {
64  try {
65    const raport = await przygotujRaportDinozaura("TREX-001");
66    console.log("Raport gotowy:");
67    console.log(JSON.stringify(raport, null, 2));
68
69    // Próba pobrania nieistniejącego dinozaura
70    const nieistniejący = await pobierzDaneDinozauraZAPI("INDOMINUS-001")
71      .catch(error => {
72        console.error(`Wystąpił błąd: ${error.message}`);
73        return "Nieznany dinozaur";
74      });
75
76    console.log(`Wynik dla nieistniejącego: ${nieistniejący}`);
77  } catch (error) {
78    console.error(`Wystąpił błąd: ${error}`);
79  }
80}
81
82// Wywołanie funkcji
83przykładUżyciaAsync();

W powyższym przykładzie zdefiniowaliśmy kilka funkcji asynchronicznych zwracających różne typy obietnic (Promise<string>, Promise<boolean> i Promise<object>). TypeScript zapewnia pełne wsparcie typów dla tych funkcji i pozwala na bezpieczne łączenie operacji asynchronicznych.

Podsumowanie

Typowanie parametrów i zwracanych wartości funkcji to jeden z fundamentalnych elementów TypeScript, który pomaga w tworzeniu bezpiecznego, przewidywalnego i łatwego w utrzymaniu kodu. W kontekście naszego Parku Jurajskiego, dobre typowanie funkcji jest jak solidne protokoły bezpieczeństwa - pomagają zapobiec potencjalnym katastrofom, zanim się wydarzą.

| Technika | Zastosowanie w Parku Jurajskim | |----------|----------------------------------| | Podstawowe typowanie funkcji | Funkcje obliczające wymagania pokarmowe dinozaurów | | Parametry opcjonalne i domyślne | Planowanie badań dinozaurów z różnymi priorytetami | | Funkcje void | Rejestrowanie zmian w systemach bezpieczeństwa | | Union types w zwracanych wartościach | Pobieranie danych dinozaurów w różnych formatach | | Typy funkcji | Definiowanie funkcji alarmowych dla procedur bezpieczeństwa | | Callbacki | Monitorowanie zdrowia dinozaurów | | Funkcje generyczne | Filtrowanie i przetwarzanie różnych typów danych | | Przeciążanie funkcji | Generowanie różnych typów identyfikatorów | | Funkcje asynchroniczne | Pobieranie danych z API i generowanie raportów |

Dr. Wu podsumowuje: "W Parku Jurajskim każda procedura musi być precyzyjnie zdefiniowana i wykonana, aby zapewnić bezpieczeństwo zarówno gościom, jak i naszym cennym okazom. Podobnie w TypeScript, prawidłowe typowanie funkcji zapewnia, że każda operacja odbędzie się dokładnie tak, jak zaplanowano - bez niespodzianek. A jak wszyscy wiemy, w świecie dinozaurów niespodzianki rzadko bywają przyjemne."

Ir a CodeWorlds