Witaj z powrotem w naszej podróży po języku TypeScript w Parku Jurajskim! Dziś Dr. Henry Wu ma dla Ciebie szczególną lekcję. Tak jak kategoryzacja gatunków dinozaurów jest kluczowa dla ich właściwej hodowli i opieki, tak samo kategoryzacja danych w TypeScript jest fundamentalnym elementem pisania bezpiecznego kodu.
Bez odpowiedniej kategoryzacji, chaos szybko rozlałby się po Parku Jurajskim - wyobraź sobie karmienie drapieżników paszą dla roślinożerców lub umieszczenie małych, łagodnych gatunków w wybiegach wielkich drapieżników.
W programowaniu, typy pełnią podobną rolę - zapobiegają "mieszaniu gatunków" danych, które nie powinny być mieszane. Sprawdźmy podstawowe typy danych w TypeScript, wykorzystując przykłady związane z zarządzaniem parkiem.
Typ
string w TypeScript reprezentuje teksty - nazwy gatunków, opisy, identyfikatory i inne dane tekstowe.1// Deklaracja zmiennych typu string
2let nazwaGatunku: string = "Tyrannosaurus Rex";
3let kodDNA: string = "ACGTTGCA";
4let oznaczeniePaddocka: string = "P-12";
5
6// Operacje na stringach
7let pełnyOpis: string = `${nazwaGatunku} (kod DNA: ${kodDNA}) - wybieg ${oznaczeniePaddocka}`;
8console.log(pełnyOpis.toUpperCase()); // Wyświetla: "TYRANNOSAURUS REX (KOD DNA: ACGTTGCA) - WYBIEG P-12"Typ
number obsługuje zarówno liczby całkowite, jak i zmiennoprzecinkowe. Jest idealny do reprezentowania wieku dinozaurów, ich wagi, budżetu parku i innych wartości liczbowych.1// Deklaracja zmiennych typu number
2let wiekDinozaura: number = 5; // w latach
3let wagaDinozaura: number = 7500.5; // w kilogramach
4let temperaturaCiała: number = 38.2; // w stopniach Celsjusza
5
6// Operacje matematyczne
7let dziennaRacjaŻywieniowa: number = wagaDinozaura * 0.05; // 5% wagi dziennie
8let rocznyKosztUtrzymania: number = dziennaRacjaŻywieniowa * 365 * 10; // koszt karmy w dolarachTyp
boolean reprezentuje wartości prawda/fałsz, idealne do śledzenia statusów, warunków czy flag w systemie parku.1// Deklaracja zmiennych typu boolean
2let jestDrapieżnikiem: boolean = true;
3let jestAktywny: boolean = false;
4let jestDorosły: boolean = wiekDinozaura >= 3; // wartość wyliczona
5
6// Zastosowanie w logice warunkowej
7if (jestDrapieżnikiem && jestAktywny) {
8 console.log("UWAGA: Aktywny drapieżnik! Sprawdź zabezpieczenia wybiegu!");
9}
10
11// Wykorzystanie w obiekcie konfiguracyjnym
12let protokółBezpieczeństwa = {
13 wymagaPodwójnegoOgrodzenia: jestDrapieżnikiem,
14 wymagaMonitoringuNocnego: jestAktywny,
15 dozwoloneDlaZwiedzających: !jestDrapieżnikiem || !jestAktywny
16};Typ
any jest jak nieznany gatunek dinozaura, który może zachowywać się w nieprzewidywalny sposób. Pozwala na przypisanie dowolnej wartości do zmiennej i wykonywanie na niej dowolnych operacji - co może być niebezpieczne!1// Deklaracja zmiennych typu any
2let próbkaBadawcza: any = "DNA-123";
3próbkaBadawcza = 42; // Możemy zmienić typ na number
4próbkaBadawcza = true; // Możemy zmienić typ na boolean
5próbkaBadawcza = { typ: "krew", wiek: "nieznany" }; // Możemy zmienić typ na obiekt
6
7// Niebezpieczne operacje
8próbkaBadawcza.nieistniejącaMetoda(); // TypeScript nie zgłosi błędu!UWAGA: Dr. Wu stanowczo odradza nadużywanie typu
– to jak wpuszczanie niezidentyfikowanych dinozaurów do parku bez odpowiednich zabezpieczeń! Używaj go tylko w ostateczności, gdy naprawdę nie wiesz, jakiego typu dane otrzymasz.any
Typ
unknown jest jak nowy gatunek dinozaura w kwarantannie - zanim go wypuścisz, musisz dokładnie sprawdzić jego właściwości.1// Deklaracja zmiennych typu unknown
2let noweOdkrycie: unknown = pobierzDaneZWykopaliska();
3
4// Nie możemy wykonywać operacji bezpośrednio
5// noweOdkrycie.metoda(); // Error: Object is of type 'unknown'
6
7// Musimy najpierw sprawdzić typ
8if (typeof noweOdkrycie === "string") {
9 console.log(noweOdkrycie.toUpperCase()); // OK
10} else if (typeof noweOdkrycie === "number") {
11 console.log(noweOdkrycie.toFixed(2)); // OK
12} else if (noweOdkrycie instanceof DinoFragment) {
13 console.log(noweOdkrycie.analizujDNA()); // OK
14}Typy literałowe (literal types) pozwalają na zdefiniowanie ścisłego zbioru dozwolonych wartości, co jest przydatne np. przy definiowaniu gatunków dinozaurów czy stref bezpieczeństwa.
1// Typy literałowe
2type GatunekDrapieżnika = "Tyrannosaurus" | "Velociraptor" | "Spinosaurus";
3type PoziomZagrożenia = 1 | 2 | 3 | 4 | 5;
4type StatusWybiegu = "aktywny" | "w konserwacji" | "zamknięty";
5
6// Wykorzystanie typów literałowych
7let obecnyDrapieżnik: GatunekDrapieżnika = "Velociraptor";
8let zagrożenie: PoziomZagrożenia = 4;
9let statusWybieguT: StatusWybiegu = "aktywny";
10
11// Próba przypisania niedozwolonej wartości spowoduje błąd
12// obecnyDrapieżnik = "Stegosaurus"; // Error: Type '"Stegosaurus"' is not assignable to type 'GatunekDrapieżnika'TypeScript potrafi automatycznie wywnioskować typ zmiennej na podstawie przypisanej wartości, co pozwala na pisanie bardziej zwięzłego kodu.
1// Automatyczne wykrywanie typów
2let nazwaDino = "Blue"; // TypeScript wywnioskuje typ string
3let wiek = 3; // TypeScript wywnioskuje typ number
4let jestAktywna = true; // TypeScript wywnioskuje typ boolean
5
6// TypeScript zapobiega błędnemu przypisaniu
7// nazwaDino = 42; // Error: Type 'number' is not assignable to type 'string'Union types pozwalają na określenie, że zmienna może przyjmować wartości kilku różnych typów, co jest przydatne w wielu scenariuszach parku.
1// Deklaracja zmiennej, która może być string lub number
2let identyfikator: string | number;
3
4identyfikator = "TREX-001"; // OK
5identyfikator = 12345; // OK
6// identyfikator = true; // Error: Type 'boolean' is not assignable to type 'string | number'
7
8// Funkcja obsługująca różne typy dinozaurów
9function przetwórzDane(dane: string | number | boolean) {
10 if (typeof dane === "string") {
11 return dane.toUpperCase();
12 } else if (typeof dane === "number") {
13 return dane.toFixed(2);
14 } else {
15 return dane ? "AKTYWNY" : "NIEAKTYWNY";
16 }
17}W TypeScript,
null i undefined to specjalne wartości, które mogą być użyteczne do reprezentowania braku danych, np. gdy dinozaur jeszcze nie został oznaczony tagiem RFID.1// Z włączoną opcją strictNullChecks w tsconfig.json
2let tagRFID: string | null = null; // Dinozaur jeszcze nie otrzymał tagu
3let ostatniBadanie: Date | undefined; // Badanie jeszcze nie było przeprowadzone
4
5// Sprawdzanie przed użyciem
6function sprawdźStatus(dino: { nazwa: string, tag: string | null }) {
7 if (dino.tag === null) {
8 return `${dino.nazwa} nie posiada tagu RFID - wymaga oznaczenia`;
9 } else {
10 return `${dino.nazwa} oznaczony tagiem ${dino.tag}`;
11 }
12}Rozważmy system monitorowania zdrowia dinozaurów, gdzie używamy różnych typów danych:
1// Interfejs opisujący strukturę danych dinozaura
2interface DaneDinozaura {
3 id: number;
4 nazwa: string;
5 gatunek: string;
6 wiek: number;
7 waga: number;
8 jestDrapieżnikiem: boolean;
9 statusZdrowia: "dobry" | "średni" | "wymaga uwagi" | "krytyczny" | null;
10 tagRFID: string | null;
11 ostatnieBadanie: Date | undefined;
12}
13
14// Funkcja sprawdzająca, czy dinozaur wymaga interwencji weterynarza
15function wymagaInterwencji(dino: DaneDinozaura): boolean {
16 // Dinozaur wymaga interwencji, jeżeli:
17 // - jego status zdrowia jest krytyczny
18 // - nie miał badania w ciągu ostatnich 30 dni
19 // - nie posiada tagu RFID
20
21 const dzisiaj = new Date();
22 const trzydzieściDniWstyecz = new Date();
23 trzydzieściDniWstyecz.setDate(dzisiaj.getDate() - 30);
24
25 return (
26 dino.statusZdrowia === "krytyczny" ||
27 dino.statusZdrowia === null ||
28 dino.tagRFID === null ||
29 (dino.ostatnieBadanie === undefined || dino.ostatnieBadanie < trzydzieściDniWstyecz)
30 );
31}
32
33// Przykładowe wykorzystanie
34const raptorBlue: DaneDinozaura = {
35 id: 101,
36 nazwa: "Blue",
37 gatunek: "Velociraptor",
38 wiek: 5,
39 waga: 350,
40 jestDrapieżnikiem: true,
41 statusZdrowia: "dobry",
42 tagRFID: "VR-101-BLUE",
43 ostatnieBadanie: new Date("2023-08-15")
44};
45
46const trixie: DaneDinozaura = {
47 id: 205,
48 nazwa: "Trixie",
49 gatunek: "Triceratops",
50 wiek: 12,
51 waga: 8500,
52 jestDrapieżnikiem: false,
53 statusZdrowia: "wymaga uwagi",
54 tagRFID: "TC-205-TRIXIE",
55 ostatnieBadanie: undefined
56};
57
58console.log(`Blue wymaga interwencji: ${wymagaInterwencji(raptorBlue)}`);
59console.log(`Trixie wymaga interwencji: ${wymagaInterwencji(trixie)}`);Właściwe używanie typów podstawowych w TypeScript jest jak precyzyjne zarządzanie różnymi gatunkami dinozaurów w Parku Jurajskim - zapewnia bezpieczeństwo i przewidywalność.
| Typ | Zastosowanie w Parku Jurajskim | Przykład | |-----|----------------------------------|----------| | string | Nazwy, opisy, identyfikatory | "Velociraptor", "P-12" | | number | Wiek, waga, koszty | 5, 7500.5, 38.2 | | boolean | Statusy, warunki, flagi | true, false | | any | Dane o nieznanej strukturze (używaj z rozwagą!) | System legacy, dane zewnętrzne | | unknown | Bezpieczniejsza alternatywa dla any | Dane, które wymagają walidacji | | union types | Wartości, które mogą być różnych typów | string | number | null | | literal types | Ograniczony zestaw wartości | "aktywny" | "nieaktywny" |
W następnej lekcji przyjrzymy się bardziej złożonym typom, takim jak tablice, krotki i enumeracje, które pozwolą nam na jeszcze lepsze modelowanie struktury danych naszego parku.
Dr. Henry Wu przypomina: "Tak jak w genetyce dinozaurów, w TypeScript precyzja typów jest kluczem do sukcesu i uniknięcia... niespodzianek."