Kurs JavaScript i TypeScript · Moduł 6: Podstawy TypeScript
Typy union i intersection
W tej lekcji4
Witaj w zaawansowanym laboratorium typów TypeScript w Parku Jurajskim! Dr. Henry Wu jest dziś szczególnie podekscytowany, ponieważ będziemy omawiać dwa potężne mechanizmy TypeScript, które można porównać do jego najbardziej ambitnych projektów inżynierii genetycznej: typy union (unii) i intersection (przecięcia).
Union Types - czyli "albo to, albo to"
Typ union (unii) pozwala zmiennej przyjmować wartości jednego z kilku różnych typów. To trochę jak wybieg hybrydowy w parku, który może pomieścić różne gatunki dinozaurów, ale tylko jeden rodzaj na raz.
Podstawowa składnia typów union
Typ union tworzymy za pomocą operatora | (pionowa kreska):
1// Zmienna może być typu string LUB number
2let identyfikatorDinozaura: string | number;
3
4identyfikatorDinozaura = "TREX-01"; // Ok, string jest dozwolony
5identyfikatorDinozaura = 12345; // Ok, number jest dozwolony
6// identyfikatorDinozaura = true; // Błąd! boolean nie jest częścią unii string | numberPraktyczne zastosowania typów union
Typy union są niezwykle przydatne w wielu praktycznych scenariuszach w Parku Jurajskim:
1. Obsługa różnych formatów identyfikatorów
1// Funkcja, która może przyjąć różne typy identyfikatorów
2function znajdźDinozaura(id: string | number): void {
3 // Musimy sprawdzić typ, zanim wykonamy operacje specyficzne dla danego typu
4 if (typeof id === "string") {
5 console.log(`Szukam dinozaura o kodzie: ${id.toUpperCase()}`);
6 } else {
7 console.log(`Szukam dinozaura o numerze: ${id.toFixed(0)}`);
8 }
9}
10
11znajdźDinozaura("RAPTOR-BLUE"); // "Szukam dinozaura o kodzie: RAPTOR-BLUE"
12znajdźDinozaura(42); // "Szukam dinozaura o numerze: 42"2. Funkcje zwracające różne typy
1// Funkcja, która może zwrócić dinozaura lub komunikat o błędzie
2function pobierzDaneDinozaura(id: string):
3 { nazwa: string; gatunek: string; wiek: number } | string {
4
5 // Symulacja bazy danych
6 const bazaDanych = new Map([
7 ["TRex1", { nazwa: "Rex", gatunek: "Tyrannosaurus", wiek: 7 }],
8 ["Rap1", { nazwa: "Blue", gatunek: "Velociraptor", wiek: 4 }]
9 ]);
10
11 const dinozaur = bazaDanych.get(id);
12
13 if (dinozaur) {
14 return dinozaur; // Zwraca obiekt dinozaura
15 } else {
16 return `Nie znaleziono dinozaura o ID: ${id}`; // Zwraca komunikat błędu
17 }
18}
19
20const wynik = pobierzDaneDinozaura("TRex1");
21// Musimy sprawdzić typ zwróconej wartości
22if (typeof wynik === "string") {
23 console.log(`Błąd: ${wynik}`);
24} else {
25 console.log(`Znaleziono: ${wynik.nazwa}, gatunek: ${wynik.gatunek}`);
26}3. Obsługa opcjonalnych parametrów
1// Funkcja tworząca raport, która może przyjąć różne parametry filtrowania
2function generujRaportDinozaurów(
3 filtr?: { gatunek?: string; minWiek?: number; drapieżniki?: boolean }
4): string {
5 let raport = "Raport dinozaurów:\n";
6
7 if (filtr) {
8 raport += "Filtry:";
9 if (filtr.gatunek) raport += ` Gatunek=${filtr.gatunek}`;
10 if (filtr.minWiek) raport += ` MinWiek=${filtr.minWiek}`;
11 if (filtr.drapieżniki !== undefined) raport += ` TylkoDrapieżniki=${filtr.drapieżniki}`;
12 } else {
13 raport += "Brak filtrów - pokazuję wszystkie dinozaury";
14 }
15
16 return raport;
17}
18
19console.log(generujRaportDinozaurów()); // Bez filtrów
20console.log(generujRaportDinozaurów({ gatunek: "Velociraptor" })); // Z filtrem gatunku
21console.log(generujRaportDinozaurów({ minWiek: 5, drapieżniki: true })); // Z wieloma filtramiDiscriminated Unions (Unie dyskryminacyjne)
Unie dyskryminacyjne to zaawansowana technika używania typów union z "właściwością dyskryminującą", która pozwala TypeScriptowi rozpoznać, z którym typem mamy do czynienia. To jak system identyfikacji dinozaurów w parku, który pozwala natychmiast rozpoznać, czy mamy do czynienia z roślinożercą czy drapieżnikiem.
1// Definiowanie interfejsów z właściwością dyskryminującą "typ"
2interface Roślinożerca {
3 typ: "roślinożerca";
4 dieta: string[];
5 poziomAgresji: number; // 1-10
6}
7
8interface Drapieżnik {
9 typ: "drapieżnik";
10 ofiary: string[];
11 siłaUgryzienia: number; // w PSI
12}
13
14// Typ będący unią dwóch interfejsów
15type Dinozaur = Roślinożerca | Drapieżnik;
16
17// Funkcja korzystająca z unii dyskryminacyjnej
18function zarządzajDinozaurem(dino: Dinozaur): void {
19 // Sprawdzamy właściwość dyskryminującą
20 switch (dino.typ) {
21 case "roślinożerca":
22 // TypeScript wie, że tutaj dino jest typu Roślinożerca
23 console.log(`Przygotuj paszę: ${dino.dieta.join(", ")}`);
24 if (dino.poziomAgresji > 7) {
25 console.log("Uwaga: Roślinożerca z wysokim poziomem agresji!");
26 }
27 break;
28 case "drapieżnik":
29 // TypeScript wie, że tutaj dino jest typu Drapieżnik
30 console.log(`Przygotuj mięso dla: ${dino.ofiary.join(", ")}`);
31 if (dino.siłaUgryzienia > 10000) {
32 console.log("Uwaga: Bardzo niebezpieczny drapieżnik!");
33 }
34 break;
35 }
36}
37
38// Przykłady użycia
39const triceratops: Roślinożerca = {
40 typ: "roślinożerca",
41 dieta: ["paprocie", "cykady", "iglaste"],
42 poziomAgresji: 6
43};
44
45const tRex: Drapieżnik = {
46 typ: "drapieżnik",
47 ofiary: ["triceratops", "edmontosaurus", "pachycephalosaurus"],
48 siłaUgryzienia: 12800
49};
50
51zarządzajDinozaurem(triceratops);
52zarządzajDinozaurem(tRex);Intersection Types - czyli "to i to"
Typ intersection (przecięcia) pozwala na połączenie wielu typów w jeden, bardziej złożony typ. To jak eksperymenty Dr. Wu z łączeniem DNA różnych dinozaurów, by stworzyć zupełnie nowe gatunki o cechach wszystkich "składników".
Podstawowa składnia typów intersection
Typ intersection tworzymy za pomocą operatora &:
1// Definiowanie interfejsów podstawowych cech
2interface PodstawowyDinozaur {
3 id: number;
4 nazwa: string;
5 gatunek: string;
6 wiek: number;
7}
8
9interface CechyFizyczne {
10 wysokość: number; // w metrach
11 długość: number; // w metrach
12 waga: number; // w kilogramach
13}
14
15interface CechyBehawioralne {
16 poziomAgresji: number; // 1-10
17 terytorialny: boolean;
18 społeczny: boolean;
19}
20
21// Tworzenie typu będącego przecięciem trzech interfejsów
22type PełnyProfilDinozaura = PodstawowyDinozaur & CechyFizyczne & CechyBehawioralne;
23
24// Teraz obiekt musi implementować wszystkie właściwości ze wszystkich trzech interfejsów
25const velociraptor: PełnyProfilDinozaura = {
26 // Z PodstawowyDinozaur
27 id: 101,
28 nazwa: "Blue",
29 gatunek: "Velociraptor",
30 wiek: 4,
31
32 // Z CechyFizyczne
33 wysokość: 0.5,
34 długość: 2,
35 waga: 15,
36
37 // Z CechyBehawioralne
38 poziomAgresji: 8,
39 terytorialny: true,
40 społeczny: true
41};Praktyczne zastosowania typów intersection
Typy intersection są szczególnie przydatne w budowaniu złożonych systemów w Parku Jurajskim:
1. Kompozycja zachowań
1// Definiowanie różnych umiejętności
2interface Pływający {
3 prędkośćPływania: number; // km/h
4 maksGłębokość: number; // metry
5 wytrzymałośćPodWodą: number; // minuty
6}
7
8interface Latający {
9 rozpiętośćSkrzydeł: number; // metry
10 prędkośćLotu: number; // km/h
11 maksWysokość: number; // metry
12}
13
14// Dinozaur, który potrafi i pływać, i latać (jak Pteranodon)
15type LatającyIPływającyDinozaur = PodstawowyDinozaur & Latający & Pływający;
16
17const pteranodon: LatającyIPływającyDinozaur = {
18 id: 201,
19 nazwa: "Pterri",
20 gatunek: "Pteranodon",
21 wiek: 12,
22
23 // Umiejętności latania
24 rozpiętośćSkrzydeł: 8,
25 prędkośćLotu: 90,
26 maksWysokość: 500,
27
28 // Umiejętności pływania
29 prędkośćPływania: 20,
30 maksGłębokość: 10,
31 wytrzymałośćPodWodą: 3
32};2. Rozszerzanie istniejących typów
1// Podstawowy interfejs bezpieczeństwa dla wszystkich wybiegów
2interface PodstawowySystemBezpieczeństwa {
3 podwójneOgrodzenie: boolean;
4 monitoringWideo: boolean;
5 czujnikiRuchu: boolean;
6}
7
8// Dodatkowe środki bezpieczeństwa dla drapieżników
9interface ZabezpieczeniaDlaDrapieżników {
10 napięcieElektryczne: number; // wolty
11 grubośćŚcian: number; // cm
12 kopułaZabezpieczająca: boolean;
13}
14
15// Pełny system bezpieczeństwa dla wybiegu drapieżników
16type WybiegDrapieżnika = PodstawowySystemBezpieczeństwa & ZabezpieczeniaDlaDrapieżników;
17
18// Używamy intersection do dodania informacji o paddle
19type WybiegTRex = WybiegDrapieżnika & {
20 obszar: number; // hektary
21 ukształtowanieTerenu: string[];
22 roślinnośćWiarygodna: boolean;
23};
24
25const wybiegRex: WybiegTRex = {
26 // PodstawowySystemBezpieczeństwa
27 podwójneOgrodzenie: true,
28 monitoringWideo: true,
29 czujnikiRuchu: true,
30
31 // ZabezpieczeniaDlaDrapieżników
32 napięcieElektryczne: 10000,
33 grubośćŚcian: 50,
34 kopułaZabezpieczająca: false,
35
36 // Specyficzne dla WybiegTRex
37 obszar: 8,
38 ukształtowanieTerenu: ["wysoka trawa", "wzgórza", "strumień"],
39 roślinnośćWiarygodna: true
40};3. Łączenie funkcjonalności w złożonych systemach
1// Interfejs systemu obserwacji
2interface SystemObserwacji {
3 kamery: number;
4 rozdzielczość: string;
5 śledzeniePodczerwienią: boolean;
6
7 rozpocznijNagrywanie(): void;
8 zatrzymajNagrywanie(): void;
9}
10
11// Interfejs systemu alarmowego
12interface SystemAlarmowy {
13 sygnałDźwiękowy: boolean;
14 sygnałŚwietlny: boolean;
15 powiadomienieSMS: boolean;
16
17 uruchomAlarm(poziom: number): void;
18 wyłączAlarm(): void;
19}
20
21// Złożony system bezpieczeństwa łączący obie funkcjonalności
22type SystemBezpieczeństwaParku = SystemObserwacji & SystemAlarmowy;
23
24// Implementacja systemu bezpieczeństwa
25class PełnySystemBezpieczeństwa implements SystemBezpieczeństwaParku {
26 // SystemObserwacji
27 kamery: number = 24;
28 rozdzielczość: string = "4K";
29 śledzeniePodczerwienią: boolean = true;
30
31 rozpocznijNagrywanie(): void {
32 console.log("Rozpoczynam nagrywanie ze wszystkich kamer");
33 }
34
35 zatrzymajNagrywanie(): void {
36 console.log("Zatrzymuję nagrywanie");
37 }
38
39 // SystemAlarmowy
40 sygnałDźwiękowy: boolean = true;
41 sygnałŚwietlny: boolean = true;
42 powiadomienieSMS: boolean = true;
43
44 uruchomAlarm(poziom: number): void {
45 console.log(`Uruchamiam alarm poziomu ${poziom}!`);
46 if (this.sygnałDźwiękowy) console.log("Syreny włączone");
47 if (this.sygnałŚwietlny) console.log("Światła ostrzegawcze włączone");
48 if (this.powiadomienieSMS) console.log("Wysyłam powiadomienia SMS do personelu");
49 }
50
51 wyłączAlarm(): void {
52 console.log("Wyłączam wszystkie systemy alarmowe");
53 }
54
55 // Dodatkowe metody specyficzne dla pełnego systemu
56 uruchomProcedurębezpieczeństwa(kodZagrożenia: string): void {
57 console.log(`Inicjuję procedurę bezpieczeństwa: ${kodZagrożenia}`);
58 this.rozpocznijNagrywanie();
59 this.uruchomAlarm(kodZagrożenia === "CZERWONY" ? 3 : 1);
60 }
61}
62
63// Użycie systemu
64const systemBezpieczeństwa = new PełnySystemBezpieczeństwa();
65systemBezpieczeństwa.uruchomProcedurębezpieczeństwa("CZERWONY");Połączenie union i intersection - zaawansowane przypadki
Prawdziwa potęga TypeScript ujawnia się, gdy łączymy typy union i intersection w bardziej złożone struktury - podobnie jak Dr. Wu łączy DNA różnych gatunków, aby stworzyć zupełnie nowe dinozaury.
1// Podstawowe typy dinozaurów
2interface Dinozaur {
3 id: number;
4 nazwa: string;
5 gatunek: string;
6}
7
8interface LądowyDinozaur {
9 środowisko: "lądowe";
10 prędkośćBiegu: number; // km/h
11}
12
13interface WodnyDinozaur {
14 środowisko: "wodne";
15 prędkośćPływania: number; // km/h
16 maksGłębokość: number; // metry
17}
18
19interface PowietrznyDinozaur {
20 środowisko: "powietrzne";
21 prędkośćLotu: number; // km/h
22 maksWysokość: number; // metry
23}
24
25// Typy dla różnych zdolności
26interface ZdolnościŁowieckie {
27 siłaUgryzienia: number; // PSI
28 strategiaPolowania: "zasadzka" | "pościg" | "stadna";
29}
30
31interface ZdolnościObronneRoślinożercy {
32 pancerz: boolean;
33 rogi: boolean;
34 kolce: boolean;
35 siłaObronna: number; // 1-10
36}
37
38// Złożony typ wykorzystujący union i intersection
39type DinozaurParkowy = Dinozaur &
40 (
41 (LądowyDinozaur & ZdolnościŁowieckie) |
42 (LądowyDinozaur & ZdolnościObronneRoślinożercy) |
43 (WodnyDinozaur & ZdolnościŁowieckie) |
44 (PowietrznyDinozaur & ZdolnościŁowieckie)
45 );
46
47// Przykłady użycia
48const tyranozaur: DinozaurParkowy = {
49 id: 1,
50 nazwa: "Rex",
51 gatunek: "Tyrannosaurus Rex",
52 środowisko: "lądowe",
53 prędkośćBiegu: 30,
54 siłaUgryzienia: 12800,
55 strategiaPolowania: "pościg"
56};
57
58const stegozaur: DinozaurParkowy = {
59 id: 2,
60 nazwa: "Spike",
61 gatunek: "Stegosaurus",
62 środowisko: "lądowe",
63 prędkośćBiegu: 7,
64 pancerz: true,
65 rogi: false,
66 kolce: true,
67 siłaObronna: 8
68};
69
70// Funkcja obsługująca złożone typy
71function analizujDinozaura(dino: DinozaurParkowy): void {
72 console.log(`Analizuję: ${dino.nazwa} (${dino.gatunek})`);
73
74 // Sprawdzamy środowisko
75 if (dino.środowisko === "lądowe") {
76 console.log(`Prędkość biegu: ${dino.prędkośćBiegu} km/h`);
77
78 // Sprawdzamy, czy to drapieżnik czy roślinożerca
79 if ("siłaUgryzienia" in dino) {
80 console.log(`Drapieżnik - siła ugryzienia: ${dino.siłaUgryzienia} PSI`);
81 console.log(`Strategia polowania: ${dino.strategiaPolowania}`);
82 } else if ("siłaObronna" in dino) {
83 console.log("Roślinożerca z mechanizmami obronnymi:");
84 if (dino.pancerz) console.log("- Wyposażony w pancerz");
85 if (dino.rogi) console.log("- Posiada rogi");
86 if (dino.kolce) console.log("- Posiada kolce");
87 console.log(`Siła obronna: ${dino.siłaObronna}/10`);
88 }
89 } else if (dino.środowisko === "wodne") {
90 console.log(`Wodny drapieżnik - prędkość pływania: ${dino.prędkośćPływania} km/h`);
91 console.log(`Maksymalna głębokość: ${dino.maksGłębokość} m`);
92 } else if (dino.środowisko === "powietrzne") {
93 console.log(`Powietrzny drapieżnik - prędkość lotu: ${dino.prędkośćLotu} km/h`);
94 console.log(`Maksymalna wysokość lotu: ${dino.maksWysokość} m`);
95 }
96}
97
98analizujDinozaura(tyranozaur);
99console.log("---");
100analizujDinozaura(stegozaur);Podsumowanie
Typy union i intersection są jak zaawansowane techniki inżynierii genetycznej Dr. Wu - dają nam niezwykłą moc i elastyczność w projektowaniu złożonych systemów TypeScript.
| Typ | Operator | Analogia w Parku Jurajskim | Zastosowanie | |
|---|---|---|---|---|
| Union | ` | ` | Wybieg mogący pomieścić różne dinozaury (ale tylko jeden rodzaj jednocześnie) | Zmienne, które mogą mieć różne typy |
| Discriminated Union | ` | ` z właściwością dyskryminującą | System identyfikacji różnych gatunków dinozaurów | Bezpieczna obsługa różnych wariantów typu |
| Intersection | & | Łączenie DNA z różnych dinozaurów | Łączenie interfejsów/typów w bardziej złożone struktury |
Dr. Wu podsumowuje dzisiejszą lekcję: "TypeScript, podobnie jak nasze laboratorium genetyczne, daje nam ogromne możliwości. Dzięki union i intersection types możemy tworzyć systemy dokładnie dopasowane do naszych potrzeb, łącząc proste elementy w złożone struktury. Jednak pamiętaj - z wielką mocą przychodzi wielka odpowiedzialność. Użyj tej wiedzy mądrze, aby stworzyć bezpieczny i niezawodny park."
Kod do tej lekcji: index.ts
1// Typy union i intersection w Parku Jurajskim
2console.log("Union i Intersection Types\n");
3
4// ===========================================
5// 1. UNION TYPES - typ A lub B
6// ===========================================
7console.log("=== UNION TYPES ===");
8
9// Prosty union type
10type DinosaurDiet = "carnivore" | "herbivore" | "omnivore";
11
12let trexDiet: DinosaurDiet = "carnivore";
13let brachiosaurDiet: DinosaurDiet = "herbivore";
14
15console.log("T-Rex diet:", trexDiet);
16console.log("Brachiosaurus diet:", brachiosaurDiet);
17
18// Union z różnymi typami
19type ID = number | string;
20
21let paddockId: ID = "P-01";
22let dinosaurId: ID = 123;
23
24console.log("Paddock ID:", paddockId);
25console.log("Dinosaur ID:", dinosaurId);
26
27// Union z obiektami
28interface Carnivore {
29 type: "carnivore";
30 huntingStyle: string;
31 preySize: string;
32}
33
34interface Herbivore {
35 type: "herbivore";
36 plantPreference: string;
37 grazingHours: number;
38}
39
40type Dinosaur = Carnivore | Herbivore;
41
42const trex: Carnivore = {
43 type: "carnivore",
44 huntingStyle: "ambush predator",
45 preySize: "large"
46};
47
48const triceratops: Herbivore = {
49 type: "herbivore",
50 plantPreference: "ferns and cycads",
51 grazingHours: 16
52};
53
54// Type guards dla union types
55function describeDiet(dino: Dinosaur): string {
56 if (dino.type === "carnivore") {
57 return `Carnivore: ${dino.huntingStyle}, preys on ${dino.preySize} animals`;
58 } else {
59 return `Herbivore: prefers ${dino.plantPreference}, grazes ${dino.grazingHours}h/day`;
60 }
61}
62
63console.log("\nT-Rex:", describeDiet(trex));
64console.log("Triceratops:", describeDiet(triceratops));
65
66// ===========================================
67// 2. INTERSECTION TYPES - typ A i B
68// ===========================================
69console.log("\n=== INTERSECTION TYPES ===");
70
71// Łączenie typów
72interface HasName {
73 name: string;
74}
75
76interface HasWeight {
77 weight: number;
78}
79
80interface HasDiet {
81 diet: DinosaurDiet;
82}
83
84// Intersection - musi mieć wszystkie właściwości
85type CompleteDinosaur = HasName & HasWeight & HasDiet;
86
87const velociraptor: CompleteDinosaur = {
88 name: "Blue",
89 weight: 350,
90 diet: "carnivore"
91};
92
93console.log("Complete dinosaur:", velociraptor);
94
95// Rozszerzanie interfejsów przez intersection
96interface BasicInfo {
97 id: number;
98 species: string;
99}
100
101interface LocationInfo {
102 paddockId: string;
103 zone: string;
104}
105
106interface HealthInfo {
107 isHealthy: boolean;
108 lastCheckup: Date;
109}
110
111type FullDinosaurInfo = BasicInfo & LocationInfo & HealthInfo;
112
113const rexy: FullDinosaurInfo = {
114 id: 1,
115 species: "Tyrannosaurus Rex",
116 paddockId: "P-01",
117 zone: "Carnivore Zone",
118 isHealthy: true,
119 lastCheckup: new Date()
120};
121
122console.log("\nFull info:", rexy);
123
124// ===========================================
125// 3. Łączenie Union i Intersection
126// ===========================================
127console.log("\n=== UNION + INTERSECTION ===");
128
129interface Swimmer {
130 swimSpeed: number;
131}
132
133interface Runner {
134 runSpeed: number;
135}
136
137interface Flyer {
138 flySpeed: number;
139}
140
141// Dinozaur może pływać LUB latać, ALE musi umieć biegać
142type ActiveDinosaur = Runner & (Swimmer | Flyer);
143
144const mosasaurus: ActiveDinosaur = {
145 runSpeed: 5, // na lądzie powolny
146 swimSpeed: 50 // w wodzie szybki
147};
148
149const pteranodon: ActiveDinosaur = {
150 runSpeed: 10,
151 flySpeed: 80
152};
153
154console.log("Mosasaurus:", mosasaurus);
155console.log("Pteranodon:", pteranodon);
156
157// ===========================================
158// 4. Praktyczne zastosowania
159// ===========================================
160console.log("\n=== PRAKTYCZNE ZASTOSOWANIA ===");
161
162// API Response type
163type SuccessResponse = {
164 status: "success";
165 data: any;
166};
167
168type ErrorResponse = {
169 status: "error";
170 message: string;
171 code: number;
172};
173
174type ApiResponse = SuccessResponse | ErrorResponse;
175
176function handleResponse(response: ApiResponse): void {
177 if (response.status === "success") {
178 console.log("Data received:", response.data);
179 } else {
180 console.log(`Error ${response.code}: ${response.message}`);
181 }
182}
183
184const success: ApiResponse = {
185 status: "success",
186 data: { dinosaurs: [trex, triceratops] }
187};
188
189const error: ApiResponse = {
190 status: "error",
191 message: "Paddock breach detected",
192 code: 503
193};
194
195handleResponse(success);
196handleResponse(error);
197
198// Event types
199interface BaseEvent {
200 timestamp: Date;
201 source: string;
202}
203
204interface FeedingEvent extends BaseEvent {
205 type: "feeding";
206 dinosaurId: number;
207 foodAmount: number;
208}
209
210interface EscapeEvent extends BaseEvent {
211 type: "escape";
212 dinosaurId: number;
213 paddockId: string;
214 severity: "low" | "high";
215}
216
217interface MaintenanceEvent extends BaseEvent {
218 type: "maintenance";
219 paddockId: string;
220 duration: number;
221}
222
223type ParkEvent = FeedingEvent | EscapeEvent | MaintenanceEvent;
224
225function logEvent(event: ParkEvent): void {
226 console.log(`[${event.timestamp.toISOString()}] ${event.source}`);
227
228 switch (event.type) {
229 case "feeding":
230 console.log(` Feeding dinosaur #${event.dinosaurId}: ${event.foodAmount}kg`);
231 break;
232 case "escape":
233 console.log(` ESCAPE from paddock ${event.paddockId}! Severity: ${event.severity}`);
234 break;
235 case "maintenance":
236 console.log(` Maintenance on paddock ${event.paddockId}: ${event.duration}h`);
237 break;
238 }
239}
240
241const feedingEvent: FeedingEvent = {
242 type: "feeding",
243 timestamp: new Date(),
244 source: "Automated System",
245 dinosaurId: 1,
246 foodAmount: 400
247};
248
249const escapeEvent: EscapeEvent = {
250 type: "escape",
251 timestamp: new Date(),
252 source: "Security Alert",
253 dinosaurId: 1,
254 paddockId: "P-01",
255 severity: "high"
256};
257
258console.log("\nEvent log:");
259logEvent(feedingEvent);
260logEvent(escapeEvent);
261
262// ===========================================
263// 5. Podsumowanie
264// ===========================================
265console.log("\n=== PODSUMOWANIE ===");
266console.log("Union Types (|) - wartość może być jednym z typów");
267console.log("Intersection Types (&) - wartość musi spełniać wszystkie typy");
268console.log("Type Guards - sprawdzanie typu w runtime");
269console.log("Discriminated Unions - rozróżnianie po polu");
270
271console.log("\nUnion i Intersection Types opanowane!");Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Co oznacza typ string | number w TypeScript?
2. Co robi typ A & B (intersection type)?
Zadania praktyczne w grze
- Edytor kodu
Stwórz typ union DietType = 'herbivore' | 'carnivore' | 'omnivore' i intersection type AquaticDino = Dinosaur & SwimmingAbility.
- Układanie w poziomie
Ułóż elementy type alias:
- Klikanie w kolejności
Ułóż elementy definicji union type:
- Układanie w pionie
Uporządkuj kroki zawężania (narrowing) typu union w TypeScript: