Kurs JavaScript i TypeScript · Moduł 6: Podstawy TypeScript

Czym jest TypeScript i jego zalety

6 min czytania
W tej lekcji6

Wprowadzenie: Problem z parkiem dinozaurów

Witaj w nowym rozdziale naszej przygody w Parku Jurajskim! Wyobraź sobie następującą sytuację: programiści parku stworzyli system kontroli dostępu do zagród dinozaurów, który miał chronić zarówno gości, jak i pracowników. Wszystko działało świetnie, dopóki w pewnym momencie...

1// system-kontroli-dostępu.js
2
3function przyznajDostep(pracownik, poziomDostępu) {
4  if (pracownik.uprawnienia >= poziomDostępu) {
5    return true;
6  }
7  return false;
8}
9
10// W innym miejscu systemu
11const drMalcolm = {
12  imie: "Ian",
13  nazwisko: "Malcolm",
14  rola: "Matematyk"
15  // ups... brak pola 'uprawnienia'!
16};
17
18// Próba dostępu do zagrody dinozaurów
19const dostępDoT_Rex = przyznajDostep(drMalcolm, 5);
20console.log("Dostęp do zagrody T-Rex:", dostępDoT_Rex); // false, ale bez błędu!
21
22// Później w kodzie...
23if (dostępDoT_Rex) {
24  otworz_brame_do_zagrody('t-rex');  // Ta operacja nigdy nie zostanie wykonana
25} else {
26  console.log("Dr Malcolm nie ma dostępu"); // To się wykona, ale nikt nie zauważył błędu
27}

Czy zauważyłeś, co poszło nie tak? W obiekcie drMalcolm zabrakło właściwości uprawnienia, przez co system niepoprawnie odmówił mu dostępu! W JavaScript ta sytuacja nie wygenerowała żadnego błędu - po prostu właściwość uprawnienia była undefined, co przy porównaniu z liczbą dało wynik false.

Wyobraź sobie teraz konsekwencje takiej sytuacji w prawdziwym parku dinozaurów:

  1. Dr Malcolm nie może wejść do swojej strefy pracy
  2. Systemy bezpieczeństwa nie działają jak powinny
  3. Co gorsza - nikt nie wie, że istnieje problem!

To właśnie w takich sytuacjach przydaje się TypeScript.

Czym jest TypeScript?

TypeScript to nadzbiór (superset) języka JavaScript, który dodaje opcjonalne statyczne typowanie. Został stworzony przez Microsoft i jest rozwijany jako projekt open source.

Wyobraź sobie TypeScript jako zaawansowany system bezpieczeństwa dla Parku Jurajskiego:

  • JavaScript to park bez kamer i czujników - wszystko działa, dopóki nic złego się nie wydarzy
  • TypeScript to park wyposażony w kamery, czujniki ruchu i system alarmowy, który wykrywa problemy ZANIM dinozaury uciekną z wybiegów

Ta sama sytuacja w TypeScript wyglądałaby tak:

1// system-kontroli-dostępu.ts
2
3// Definiujemy interfejs określający, jak powinien wyglądać obiekt pracownika
4interface Pracownik {
5  imie: string;
6  nazwisko: string;
7  rola: string;
8  uprawnienia: number; // Wymagane pole!
9}
10
11function przyznajDostep(pracownik: Pracownik, poziomDostępu: number): boolean {
12  if (pracownik.uprawnienia >= poziomDostępu) {
13    return true;
14  }
15  return false;
16}
17
18// W innym miejscu systemu
19const drMalcolm = {
20  imie: "Ian",
21  nazwisko: "Malcolm",
22  rola: "Matematyk"
23  // TypeScript wyłapie błąd: Property 'uprawnienia' is missing in type
24  // '{ imie: string; nazwisko: string; rola: string; }' but required in type 'Pracownik'.
25};
26
27// Ta linia spowoduje błąd kompilacji - TypeScript nas ochroni!
28const dostępDoT_Rex = przyznajDostep(drMalcolm, 5);

W powyższym przykładzie TypeScript wykryje błąd już na etapie pisania kodu, zanim oprogramowanie zostanie uruchomione. To jak system ostrzegający nas, że drzwi do zagrody są otwarte, zanim dinozaur zdąży uciec!

Najważniejsze zalety TypeScript

1. Wykrywanie błędów na wczesnym etapie

Podobnie jak system monitoringu w Parku Jurajskim, TypeScript wykrywa potencjalne problemy jeszcze na etapie pisania kodu:

1function nakarmDinozaura(dinozaur: { gatunek: string; dietaTyp: string; }): void {
2  let jedzenie;
3
4  if (dinozaur.dietaTyp === 'roślinożerny') {
5    jedzenie = 'liście paproci';
6  } else if (dinozaur.dietaTyp === 'mięsożerny') {
7    jedzenie = 'mięso';
8  }
9
10  console.log(`Karmienie ${dinozaur.gatunek}a jedzeniem: ${jedzenie}`);
11}
12
13// TypeScript ostrzeże, że literówka 'roslinozerca' nie pasuje do żadnego warunku
14const triceratops = { gatunek: 'Triceratops', dietaTyp: 'roslinozerca' };
15nakarmDinozaura(triceratops);
16// Bez TypeScript ten dinozaur dostałby "undefined" jako jedzenie!

2. Lepsza dokumentacja kodu

TypeScript działa jak dokładny inwentarz wszystkich dinozaurów w parku:

1// Bez TypeScript - co to są za parametry? Co zwraca ta funkcja?
2function utworzWybieg(id, nazwa, pojemnosc, typOgrodzenia) {
3  //
4}
5
6// Z TypeScript - natychmiastowa dokumentacja!
7function utworzWybieg(
8  id: number,
9  nazwa: string,
10  pojemnosc: number,
11  typOgrodzenia: 'standardowe' | 'elektryczne' | 'wzmocnione'
12): { id: number; status: 'aktywny' | 'w budowie' | 'zamknięty' } {
13  //
14  return { id, status: 'w budowie' };
15}

3. Lepsze wsparcie IDE (podpowiadanie kodu)

Dzięki TypeScript, twoje środowisko programistyczne (IDE) będzie dokładnie wiedzieć, jakie operacje możesz wykonać na danym obiekcie:

1const dinosaur = { name: 'Rex', species: 'T-Rex', weight: 8000 }
2
3dinosaur.name.toUpperCase() // po kropce edytor podpowiada name, species i weight, a po drugiej kropce metody stringa
4dinosaur.height // błąd: Property 'height' does not exist on type '{ name: string; species: string; weight: number; }'

To jak mapa Parku Jurajskiego z dokładnymi wskazówkami, gdzie znajdują się poszczególne wybiegi i jakie dinozaury są w nich trzymane.

4. Bezpieczniejsze refaktoryzacje

Kiedy wprowadzasz zmiany w systemie zarządzania parkiem, TypeScript ostrzega cię o wszystkich miejscach, które wymagają aktualizacji:

1// Przed refaktoryzacją
2interface Dinozaur {
3  id: number;
4  gatunek: string;
5  niebezpieczny: boolean;
6}
7
8// Po refaktoryzacji - zmiana typu pola
9interface Dinozaur {
10  id: number;
11  gatunek: string;
12  poziomZagrozenia: number; // od 1 do 10 zamiast boolean
13}
14
15// TypeScript wskaże wszystkie miejsca, gdzie używaliśmy "niebezpieczny"
16// i teraz musimy użyć "poziomZagrozenia"

5. Typy dla bibliotek zewnętrznych

Nawet jeśli używasz zewnętrznych bibliotek napisanych w czystym JavaScript, możesz korzystać z plików definicji typów, które zapewniają podpowiadanie kodu i kontrolę typów:

1// Instalacja typów dla biblioteki do analizy DNA
2// npm install --save-dev @types/dino-dna-analyzer
3
4import { analizujDNA } from 'dino-dna-analyzer';
5
6// Teraz TypeScript zna typy parametrów i zwracanych wartości
7const wynik = analizujDNA({
8  sekwencja: 'ACGTACGT',
9  gatunekBazowy: 'żaba'
10});
11
12console.log(wynik.kompletnosc); // TypeScript zna dostępne pola

6. Wsparcie dla nowoczesnych funkcji JavaScript

TypeScript pozwala korzystać z najnowszych funkcji JavaScript, nawet jeśli docelowe środowisko ich nie obsługuje:

1// Użycie nowoczesnej składni JavaScript
2const dinozaury = ['T-Rex', 'Velociraptor', 'Triceratops'];
3const [najgrozniejszy, ...pozostale] = dinozaury;
4
5// Optional chaining i nullish coalescing
6const dane = {
7  park: {
8    // sektor może nie istnieć
9  }
10};
11
12const nazwaSektora = dane.park?.sektor?.nazwa ?? "Nieznany sektor";

7. Stopniowa migracja

Jedną z największych zalet TypeScript jest możliwość stopniowego wprowadzania go do istniejących projektów JavaScript:

  1. Zmień rozszerzenie pliku z .jsna.ts
  2. Początkowo ignoruj błędy za pomocą // @ts-ignore lub używając typu any
  3. Stopniowo dodawaj typy do kodu, zaczynając od najbardziej krytycznych części

To jak stopniowe usprawnianie systemów bezpieczeństwa w Parku Jurajskim, sektor po sektorze, zamiast zamykania całego parku na czas modernizacji.

Ograniczenia TypeScript

Oczywiście, jak każda technologia, TypeScript ma swoje ograniczenia:

  1. Dodatkowy etap kompilacji - kod TypeScript musi zostać przekonwertowany na JavaScript przed uruchomieniem
  2. Stroma krzywa uczenia - dla początkujących programistów JavaScript, nauka typów może być wyzwaniem
  3. Fałszywe poczucie bezpieczeństwa - TypeScript wykrywa błędy związane z typami, ale nie chroni przed błędami logicznymi
  4. Typ any - można "oszukać" system typów używając any, co niweluje zalety TypeScript

Kiedy warto użyć TypeScript?

TypeScript sprawdza się najlepiej w następujących scenariuszach:

  1. Duże projekty z wieloma programistami - jak zarządzanie całym Parkiem Jurajskim
  2. Długotrwałe projekty - gdy kod będzie utrzymywany przez długi czas
  3. Kompleksowe aplikacje biznesowe - gdy błędy mogą mieć poważne konsekwencje
  4. Biblioteki i narzędzia Open Source - aby ułatwić innym programistom korzystanie z twojego kodu

Podsumowanie

TypeScript jest jak zaawansowany system bezpieczeństwa dla Parku Jurajskiego:

  • JavaScript: "Mamy dinozaury w klatkach, wszystko powinno być w porządku."
  • TypeScript: "Każdy dinozaur jest monitorowany, mamy alert przy najmniejszej anomalii, a pracownicy mają jasne instrukcje postępowania."

Dodając typowanie do kodu JavaScript, zyskujesz:

  • Wcześniejsze wykrywanie błędów
  • Lepszą dokumentację
  • Wydajniejsze narzędzia programistyczne
  • Bezpieczniejsze refaktoryzacje

W następnych lekcjach zaczniemy szczegółowo poznawać system typów TypeScript i zobaczymy, jak możemy wykorzystać go do budowania bardziej niezawodnych systemów - takich, które nie pozwoliłyby dinozaurom uciec z parku!

Kod do tej lekcji: index.ts
1// TypeScript w Parku Jurajskim - Wprowadzenie i podstawy
2console.log("Witaj w TypeScript - Parku Jurajskim!");
3console.log("Poznajemy TypeScript i jego zalety w bezpiecznym kodzie\n");
4
5// ===========================================
6// 1. Problem z JavaScript - brak typów
7// ===========================================
8console.log("=== 1. PROBLEM Z JAVASCRIPT ===");
9
10// JavaScript - problemy z typami
11function grantAccessJS(employee: any, accessLevel: any): boolean {
12  // W JavaScript nie ma sprawdzania typów
13  if (employee.permissions >= accessLevel) {
14    return true;
15  }
16  return false;
17}
18
19// Niebezpieczne dane - brak sprawdzania
20const drMalcolmJS: any = {
21  name: "Ian Malcolm",
22  role: "Mathematician"
23  // Brak pola 'permissions'!
24};
25
26// To się wykonuje bez błędu, ale zwraca nieprawidłowy wynik
27const accessJS = grantAccessJS(drMalcolmJS, 5);
28console.log("JavaScript access result:", accessJS); // undefined >= 5 = false
29
30console.log("JavaScript pozwala na błędy typów w runtime");
31console.log("Trudne debugowanie");
32console.log("Brak IntelliSense/autouzupełniania\n");
33
34// ===========================================
35// 2. TypeScript - rozwiązanie problemu
36// ===========================================
37console.log("=== 2. TYPESCRIPT - ROZWIĄZANIE ===");
38
39// Definicja interfejsu dla pracownika
40interface Employee {
41  name: string;
42  role: string;
43  permissions: number;
44  department?: string; // Opcjonalne pole
45}
46
47// Funkcja z typami TypeScript
48function grantAccess(employee: Employee, accessLevel: number): boolean {
49  if (employee.permissions >= accessLevel) {
50    return true;
51  }
52  return false;
53}
54
55// Poprawne dane z typami
56const drMalcolm: Employee = {
57  name: "Ian Malcolm",
58  role: "Mathematician",
59  permissions: 3
60};
61
62const accessTS = grantAccess(drMalcolm, 5);
63console.log("TypeScript access result:", accessTS);
64
65console.log("TypeScript sprawdza typy w compile-time");
66console.log("Lepsze IntelliSense i autouzupełnianie");
67console.log("Wczesne wykrywanie błędów\n");
68
69// ===========================================
70// 3. Podstawowe typy TypeScript
71// ===========================================
72console.log("=== 3. PODSTAWOWE TYPY TYPESCRIPT ===");
73
74// Typy prymitywne
75let dinosaurName: string = "Tyrannosaurus Rex";
76let dinosaurAge: number = 68000000;
77let isExtinct: boolean = true;
78let unknownData: unknown = "mysterious data";
79let nothingHere: null = null;
80let notDefined: undefined = undefined;
81
82// Tablice
83let dinosaurSpecies: string[] = ["T-Rex", "Triceratops", "Velociraptor"];
84let dangerLevels: Array<number> = [9, 6, 8]; // Alternatywna składnia
85
86// Tuple - tablica o stałej długości i typach
87let dinosaurInfo: [string, number, boolean] = ["T-Rex", 8000, true];
88
89// Enum - numerowane stałe
90enum SecurityLevel {
91  Green = 1,
92  Yellow = 2,
93  Orange = 3,
94  Red = 4,
95  Critical = 5
96}
97
98let currentSecurity: SecurityLevel = SecurityLevel.Orange;
99console.log("Current security level:", SecurityLevel[currentSecurity]);
100
101// Union types - jeden z kilku typów
102type DinosaurDiet = "carnivore" | "herbivore" | "omnivore";
103let trexDiet: DinosaurDiet = "carnivore";
104
105// Literal types
106type DinosaurPeriod = "Triassic" | "Jurassic" | "Cretaceous";
107let period: DinosaurPeriod = "Cretaceous";
108
109console.log("Podstawowe typy TypeScript zdefiniowane!\n");
110
111// ===========================================
112// 4. Interfejsy i typy obiektów
113// ===========================================
114console.log("=== 4. INTERFEJSY I TYPY OBIEKTÓW ===");
115
116// Interfejs dla dinozaura
117interface Dinosaur {
118  readonly id: string; // Tylko do odczytu
119  name: string;
120  species: string;
121  diet: DinosaurDiet;
122  weight: number;
123  dangerLevel: number;
124  isActive?: boolean; // Opcjonalne
125
126  // Metody w interfejsie
127  roar(): string;
128  feed(food: string): void;
129}
130
131// Implementacja interfejsu
132class TyrannosaurusRex implements Dinosaur {
133  readonly id: string;
134  name: string;
135  species: string;
136  diet: DinosaurDiet;
137  weight: number;
138  dangerLevel: number;
139  isActive: boolean;
140
141  constructor(name: string) {
142    this.id = `DINO-${Date.now()}`;
143    this.name = name;
144    this.species = "Tyrannosaurus Rex";
145    this.diet = "carnivore";
146    this.weight = 8000;
147    this.dangerLevel = 9;
148    this.isActive = true;
149  }
150
151  roar(): string {
152    return `${this.name} roars: ROAAAAAR!`;
153  }
154
155  feed(food: string): void {
156    console.log(`${this.name} eats ${food}`);
157  }
158
159  hunt(prey: string): string {
160    return `${this.name} hunts ${prey}`;
161  }
162}
163
164const rexy = new TyrannosaurusRex("Rexy");
165console.log("Dinosaur created:", rexy.name);
166console.log("Roar:", rexy.roar());
167rexy.feed("goat");
168
169// Extending interfaces
170interface CarnivorousDinosaur extends Dinosaur {
171  huntingStyle: string;
172  packSize: number;
173  hunt(prey: string): string;
174}
175
176// Type aliases dla złożonych typów
177type DinosaurCollection = {
178  [key: string]: Dinosaur;
179};
180
181type EnclosureStatus = "secure" | "breached" | "maintenance";
182
183console.log("Interfejsy i typy obiektów zdefiniowane!\n");
184
185// ===========================================
186// 5. Generics - typy parametryczne
187// ===========================================
188console.log("=== 5. GENERICS - TYPY PARAMETRYCZNE ===");
189
190// Generic function
191function createContainer<T>(item: T): { content: T; timestamp: Date } {
192  return {
193    content: item,
194    timestamp: new Date()
195  };
196}
197
198// Użycie z różnymi typami
199const dinoContainer = createContainer<Dinosaur>(rexy);
200const stringContainer = createContainer<string>("Important data");
201const numberContainer = createContainer<number>(42);
202
203console.log("Dino container:", dinoContainer.content.name);
204console.log("String container:", stringContainer.content);
205
206// Generic interface
207interface Repository<T> {
208  items: T[];
209  add(item: T): void;
210  find(predicate: (item: T) => boolean): T | undefined;
211  getAll(): T[];
212}
213
214// Implementation dla dinozaurów
215class DinosaurRepository implements Repository<Dinosaur> {
216  items: Dinosaur[] = [];
217
218  add(dinosaur: Dinosaur): void {
219    this.items.push(dinosaur);
220    console.log(`Added ${dinosaur.name} to repository`);
221  }
222
223  find(predicate: (dinosaur: Dinosaur) => boolean): Dinosaur | undefined {
224    return this.items.find(predicate);
225  }
226
227  getAll(): Dinosaur[] {
228    return [...this.items];
229  }
230
231  findByDiet(diet: DinosaurDiet): Dinosaur[] {
232    return this.items.filter(dino => dino.diet === diet);
233  }
234}
235
236const dinoRepo = new DinosaurRepository();
237dinoRepo.add(rexy);
238
239// Generic constraints
240interface HasName {
241  name: string;
242}
243
244function logName<T extends HasName>(item: T): T {
245  console.log(`Logging: ${item.name}`);
246  return item;
247}
248
249logName(rexy); // Works - Dinosaur has name
250// logName(123); // Error - number doesn't have name
251
252console.log("Generics działają!\n");
253
254// ===========================================
255// 6. Utility Types - wbudowane typy pomocnicze
256// ===========================================
257console.log("=== 6. UTILITY TYPES ===");
258
259// Partial - wszystkie pola opcjonalne
260type PartialDinosaur = Partial<Dinosaur>;
261
262function updateDinosaur(dino: Dinosaur, updates: PartialDinosaur): Dinosaur {
263  return { ...dino, ...updates };
264}
265
266const updatedRexy = updateDinosaur(rexy, { isActive: false });
267console.log(`${updatedRexy.name} is active: ${updatedRexy.isActive}`);
268
269// Pick - wybór określonych pól
270type DinosaurSummary = Pick<Dinosaur, "name" | "species" | "dangerLevel">;
271
272function createSummary(dino: Dinosaur): DinosaurSummary {
273  return {
274    name: dino.name,
275    species: dino.species,
276    dangerLevel: dino.dangerLevel
277  };
278}
279
280const summary = createSummary(rexy);
281console.log("Dinosaur summary:", summary);
282
283// Omit - usunięcie określonych pól
284type PublicDinosaurInfo = Omit<Dinosaur, "id" | "dangerLevel">;
285
286function getPublicInfo(dino: Dinosaur): PublicDinosaurInfo {
287  const { id, dangerLevel, ...publicInfo } = dino;
288  return publicInfo;
289}
290
291// Record - mapowanie kluczy do wartości
292type DinosaurStats = Record<DinosaurDiet, number>;
293
294const dietStats: DinosaurStats = {
295  carnivore: 3,
296  herbivore: 7,
297  omnivore: 2
298};
299
300console.log("Diet statistics:", dietStats);
301
302// Required - wszystkie pola wymagane
303type RequiredDinosaur = Required<Dinosaur>;
304
305console.log("Utility types działają!\n");
306
307// ===========================================
308// 7. Zaawansowane typy
309// ===========================================
310console.log("=== 7. ZAAWANSOWANE TYPY ===");
311
312// Mapped types
313type ReadonlyDinosaur = {
314  readonly [K in keyof Dinosaur]: Dinosaur[K];
315};
316
317// Conditional types
318type DinosaurSound<T> = T extends "carnivore" ? "ROAR" : "HONK";
319
320type TRexSound = DinosaurSound<"carnivore">; // "ROAR"
321type TriceratopsSound = DinosaurSound<"herbivore">; // "HONK"
322
323// Template literal types
324type EventName<T extends string> = `dinosaur-${T}`;
325type DinosaurEvents = EventName<"fed" | "escaped" | "sleeping">;
326
327// Function types
328type DinosaurEventHandler = (dinosaur: Dinosaur, event: DinosaurEvents) => void;
329
330const eventHandler: DinosaurEventHandler = (dino, event) => {
331  console.log(`Event ${event} for ${dino.name}`);
332};
333
334eventHandler(rexy, "dinosaur-fed");
335
336console.log("Zaawansowane typy działają!\n");
337
338// ===========================================
339// 8. Praktyczny przykład - System zarządzania parkiem
340// ===========================================
341console.log("=== 8. SYSTEM ZARZĄDZANIA PARKIEM ===");
342
343// Kompleksny system typów dla parku
344interface Enclosure {
345  id: string;
346  name: string;
347  capacity: number;
348  type: "carnivore" | "herbivore" | "mixed";
349  securityLevel: SecurityLevel;
350  dinosaurs: Dinosaur[];
351  isLocked: boolean;
352}
353
354interface ParkEvent {
355  id: string;
356  timestamp: Date;
357  type: "feeding" | "escape" | "maintenance" | "visitor";
358  entityId: string;
359  severity: "low" | "medium" | "high" | "critical";
360  message: string;
361}
362
363class ParkManager {
364  private enclosures: Map<string, Enclosure> = new Map();
365  private eventLog: ParkEvent[] = [];
366
367  addEnclosure(enclosure: Omit<Enclosure, "id">): string {
368    const id = `ENC-${Date.now()}`;
369    const newEnclosure: Enclosure = { ...enclosure, id };
370    this.enclosures.set(id, newEnclosure);
371
372    this.logEvent({
373      type: "maintenance",
374      entityId: id,
375      severity: "low",
376      message: `Enclosure ${enclosure.name} created`
377    });
378
379    return id;
380  }
381
382  addDinosaurToEnclosure(dinosaurId: string, enclosureId: string): boolean {
383    const enclosure = this.enclosures.get(enclosureId);
384    if (!enclosure) {
385      console.log("Enclosure not found");
386      return false;
387    }
388
389    if (enclosure.dinosaurs.length >= enclosure.capacity) {
390      console.log("Enclosure at capacity");
391      return false;
392    }
393
394    // W prawdziwej aplikacji pobieralibyśmy dinozaura z repozytorium
395    console.log(`Dinosaur ${dinosaurId} added to ${enclosure.name}`);
396    return true;
397  }
398
399  private logEvent(event: Omit<ParkEvent, "id" | "timestamp">): void {
400    const newEvent: ParkEvent = {
401      ...event,
402      id: `EVT-${Date.now()}`,
403      timestamp: new Date()
404    };
405    this.eventLog.push(newEvent);
406  }
407
408  getEventsByType<T extends ParkEvent["type"]>(type: T): ParkEvent[] {
409    return this.eventLog.filter(event => event.type === type);
410  }
411
412  getParkStatus(): {
413    enclosureCount: number;
414    totalDinosaurs: number;
415    securityLevel: SecurityLevel;
416    recentEvents: ParkEvent[];
417  } {
418    const enclosures = Array.from(this.enclosures.values());
419    const totalDinosaurs = enclosures.reduce((sum, enc) => sum + enc.dinosaurs.length, 0);
420    const maxSecurityLevel = Math.max(...enclosures.map(enc => enc.securityLevel));
421
422    return {
423      enclosureCount: enclosures.length,
424      totalDinosaurs,
425      securityLevel: maxSecurityLevel as SecurityLevel,
426      recentEvents: this.eventLog.slice(-5)
427    };
428  }
429}
430
431// Test systemu
432const parkManager = new ParkManager();
433
434const enclosureId = parkManager.addEnclosure({
435  name: "T-Rex Paddock",
436  capacity: 2,
437  type: "carnivore",
438  securityLevel: SecurityLevel.Critical,
439  dinosaurs: [],
440  isLocked: true
441});
442
443parkManager.addDinosaurToEnclosure("rexy", enclosureId);
444
445const status = parkManager.getParkStatus();
446console.log("Park status:", status);
447
448console.log("\nTypeScript Park Management System działa!\n");
449
450// ===========================================
451// 9. Zalety TypeScript
452// ===========================================
453console.log("=== 9. ZALETY TYPESCRIPT ===");
454
455console.log("BEZPIECZEŃSTWO TYPÓW:");
456console.log("  • Wykrywanie błędów w compile-time");
457console.log("  • Zapobieganie typowym błędom JavaScript");
458console.log("  • Pewność co do struktury danych\n");
459
460console.log("LEPSZE NARZĘDZIA:");
461console.log("  • IntelliSense/autouzupełnianie");
462console.log("  • Refactoring z pewną siebie IDE");
463console.log("  • Automatyczne sprawdzanie składni\n");
464
465console.log("DOKUMENTACJA KODU:");
466console.log("  • Typy służą jako dokumentacja");
467console.log("  • Jasne API interfejsów");
468console.log("  • Czytelniejszy kod dla zespołu\n");
469
470console.log("SKALOWALNOŚĆ:");
471console.log("  • Łatwiejsze zarządzanie dużymi projektami");
472console.log("  • Lepsze współpraca w zespole");
473console.log("  • Mniejsze ryzyko regresji\n");
474
475console.log("ZGODNOŚĆ Z JAVASCRIPT:");
476console.log("  • Stopniowa migracja z JS");
477console.log("  • Używanie bibliotek JavaScript");
478console.log("  • Kompilacja do czystego JS\n");
479
480console.log("TypeScript - bezpieczniejszy JavaScript dla Parku Jurajskiego!");

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jaka jest najważniejsza zaleta TypeScript w porównaniu z JavaScript?

  2. 2. Jaka jest relacja między TypeScript a JavaScript?

To 2 z 4 pytań do tej lekcji. Pozostałe rozwiążesz w grze.

Zadania praktyczne w grze

  • Edytor kodu

    Zdefiniuj zmienną gatunekDinozaura typu string i przypisz jej wartość 'T-Rex'.

Przydatne artykuły