Instrukcja if / else

Do tej pory program wykonywał wszystkie linie po kolei, od góry do dołu. Teraz nauczy się podejmować decyzje: wykonać jeden fragment kodu, a inny pominąć — w zależności od danych.

TypeScript if / else if / else warunki 50 min
CEL LEKCJI

Czego się dziś nauczysz

  • Zapiszesz decyzję programu instrukcją if z blokiem else
  • Zbudujesz drabinkę else if i ustawisz warunki we właściwej kolejności
  • Wyjaśnisz, dlaczego zmienna zadeklarowana w bloku nie istnieje poza nim
  • Zastąpisz zagnieżdżone if wcześniejszym wyjściem lub złożonym warunkiem
  • Rozpoznasz, kiedy zamiast if lepszy jest operator warunkowy
TEORIA

Instrukcja if

schemat
if (warunek) {
    // wykona się tylko wtedy, gdy warunek jest prawdziwy
}

        ┌──────────────┐
        │   warunek?   │
        └──────┬───────┘
      prawda   │   fałsz
       ┌───────┴────────┐
       ▼                │
  ┌─────────┐           │
  │  blok   │           │
  └────┬────┘           │
       └────────┬───────┘
                ▼
         dalsza część programu
src/index.ts
const punkty = 62;

if (punkty >= 50) {
  console.log("Egzamin zdany");
}

if (punkty >= 90) {
  console.log("Wynik celujący");   // nie wykona się
}

console.log("Koniec sprawdzania");   // wykona się zawsze

W nawiasie po if stoi wyrażenie logiczne — takie jak te z lekcji 4. Może to być porównanie, zmienna typu boolean albo cały złożony warunek z && i ||.

src/index.ts — co może stać w nawiasie
const wiek = 17;
const maZgode = true;
const oceny = [5, 4, 3];

if (wiek >= 18) { }                          // porównanie
if (maZgode) { }                             // zmienna logiczna
if (!maZgode) { }                            // zaprzeczenie
if (wiek >= 16 && maZgode) { }               // warunek złożony
if (oceny.length > 0) { }                    // wynik obliczenia
if (oceny.includes(1)) { }                   // wynik metody

Zmienna logiczna nie potrzebuje porównania

Zapis if (maZgode === true) działa, ale jest nadmiarowy — maZgode już jest prawdą albo fałszem. Pisz po prostu if (maZgode) oraz if (!maZgode). Dobrze dobrana nazwa zmiennej (czy…, ma…, jest…) sprawia, że warunek czyta się jak zdanie.

TEORIA

else i else if

Blok else wykonuje się wtedy, gdy warunek był fałszywy. Wykona się dokładnie jedna z dwóch gałęzi — nigdy obie, nigdy żadna:

src/index.ts
const temperatura = 3;

if (temperatura > 0) {
  console.log("Powyżej zera");
} else {
  console.log("Mróz");
}

Gdy możliwości jest więcej, dokładamy kolejne warunki przez else if. Program sprawdza je po kolei i zatrzymuje się na pierwszym prawdziwym:

src/index.ts
const procent = 74;
let ocena: string;

if (procent >= 90) {
  ocena = "celujący";
} else if (procent >= 75) {
  ocena = "bardzo dobry";
} else if (procent >= 60) {
  ocena = "dobry";
} else if (procent >= 50) {
  ocena = "dostateczny";
} else {
  ocena = "niedostateczny";
}

console.log(`${procent}% → ${ocena}`);   // 74% → dobry

Dlaczego nie trzeba pisać procent >= 60 && procent < 75

Bo do trzeciego warunku program dociera tylko wtedy, gdy dwa poprzednie były fałszywe — czyli gdy procent jest już na pewno mniejszy niż 75. Drabinka else if sama odcina górne przedziały. Dopisywanie drugiego porównania to zbędna praca i okazja do pomyłki.

WAŻNE

Kolejność warunków decyduje o wyniku

Ten sam zestaw warunków w złej kolejności daje bezsensowne wyniki:

źle — od najmniejszego
const procent = 95;

if (procent >= 50) {
  console.log("dostateczny");        // ← program zatrzyma się TUTAJ
} else if (procent >= 75) {
  console.log("bardzo dobry");       // nigdy nieosiągalne
} else if (procent >= 90) {
  console.log("celujący");           // nigdy nieosiągalne
}

Wynik: dostateczny — mimo 95 punktów. Warunek procent >= 50 jest prawdziwy także dla 95, a program nie sprawdza już nic dalej.

Reguła

Przy progach liczbowych układaj warunki od najbardziej szczegółowego do najbardziej ogólnego — zwykle od największej wartości w dół. Ostatni else łapie wszystko, co nie pasowało wcześniej.

PRAKTYKA

Zagnieżdżanie i zasięg zmiennych

Wewnątrz bloku if może stać kolejny if. Bywa to potrzebne, ale szybko robi się nieczytelne:

trzy poziomy zagnieżdżenia — do poprawy
const zalogowany = true;
const maUprawnienia = true;
const dokumentIstnieje = true;
if (zalogowany) {
  if (maUprawnienia) {
    if (dokumentIstnieje) {
      console.log("Otwieram dokument");
    } else {
      console.log("Brak dokumentu");
    }
  } else {
    console.log("Brak uprawnień");
  }
} else {
  console.log("Zaloguj się");
}
to samo z wczesnym wyjściem — czytelniej
const zalogowany = true;
const maUprawnienia = true;
const dokumentIstnieje = true;
if (!zalogowany) {
  console.log("Zaloguj się");
} else if (!maUprawnienia) {
  console.log("Brak uprawnień");
} else if (!dokumentIstnieje) {
  console.log("Brak dokumentu");
} else {
  console.log("Otwieram dokument");
}

Ta technika nazywa się strażnikami (ang. guard clauses): najpierw odrzucasz po kolei wszystkie przypadki błędne, a właściwe działanie zostaje na końcu, na płaskim poziomie. W funkcjach (lekcja 11) będzie jeszcze wygodniej, bo zamiast else if użyjesz return.

Zasięg blokowy

Celowy błąd: zmienna komentarz poza blokiem
const punkty = 80;

if (punkty >= 50) {
  const komentarz = "gratulacje";
  console.log(komentarz);        // OK — jesteśmy w tym samym bloku
}

console.log(komentarz);          // Błąd TS2304: Cannot find name 'komentarz'.

Zmienna zadeklarowana przez let lub const wewnątrz nawiasów klamrowych żyje tylko do końca tego bloku. Jeśli wynik ma być widoczny dalej, zadeklaruj zmienną przed instrukcją if:

src/index.ts
const punkty = 80;
let komentarz: string;

if (punkty >= 50) {
  komentarz = "gratulacje";
} else {
  komentarz = "spróbuj ponownie";
}

console.log(komentarz);          // OK

Kompilator pilnuje, żeby zmienna została ustawiona

Gdybyś pominął blok else, TypeScript zgłosi TS2454: Variable 'komentarz' is used before being assigned — bo istnieje droga przez program, na której zmienna nigdy nie dostała wartości. To jedna z tych rzeczy, których zwykły JavaScript nie sprawdza.

STYL

Skróty zapisu

Gdy blok ma jedną instrukcję, klamry można pominąć — ale rób to ostrożnie:

src/index.ts
let punkty = -2;
// dopuszczalne przy krótkim, jednolinijkowym warunku
if (punkty < 0) punkty = 0;

// PUŁAPKA — druga linia wykona się ZAWSZE, mimo wcięcia
if (punkty < 0)
  console.log("Wartość ujemna");
  console.log("Poprawiam na zero");   // to już nie należy do if!

Zasada bezpieczeństwa

Wcięcie nie ma dla kompilatora żadnego znaczenia — liczą się tylko klamry. W tym kursie zawsze piszemy klamry, nawet przy jednej instrukcji. Kosztuje to dwa znaki, a oszczędza godzinę szukania błędu.

Kiedy zamiast if użyć operatora warunkowego

src/index.ts
const zdany = true;
function wyslijCertyfikat(): void { console.log("Symulacja wydania certyfikatu"); }
function zapiszNaPoprawke(): void { console.log("Symulacja zapisu na poprawkę"); }
// wybór jednej z dwóch wartości — operator warunkowy jest krótszy
const status = zdany ? "ZDANY" : "NIEZDANY";

// wykonanie różnych działań — tu potrzebny jest if
if (zdany) {
  console.log("Gratulacje!");
  wyslijCertyfikat();
} else {
  console.log("Zapraszamy na poprawkę");
  zapiszNaPoprawke();
}

Reguła jest prosta: operator warunkowy wybiera wartość, instrukcja if wybiera działanie.

Umowne dane ćwiczenia

Ocena szkolna wyliczona ze średniej oraz maksymalne liczby punktów są założeniami tego przykładu, nie oficjalnym sposobem wystawiania wyniku egzaminu. Uczymy się warunków. W zadaniu o haśle test cyfry dla pojedynczego znaku ASCII zapisuj jako znak >= "0" && znak <= "9"; Number zamienia także część białych znaków na zero.

PRZYKŁAD Z OMÓWIENIEM

Kalkulator oceny z egzaminu zawodowego

Program sprawdza poprawność danych, przelicza punkty na procenty, ustala ocenę według progów i dodaje komentarz zależny od kilku warunków naraz.

src/index.ts
// ── dane wejściowe ──
const uczen = "Marta Kowalska";
const punktyPisemny = 32;
const maksPisemny = 40;
const punktyPraktyczny = 17;
const maksPraktyczny = 20;
const obecnyNaObu = true;

const PROG_PISEMNY = 50;
const PROG_PRAKTYCZNY = 75;

console.log(`Wyniki: ${uczen}`);
console.log("─".repeat(40));

// ── 1. Strażnicy: odrzucamy dane bezsensowne ──
if (!obecnyNaObu) {
  console.log("Uczeń nieobecny na jednej z części — egzamin niezaliczony.");
} else if (punktyPisemny < 0 || punktyPisemny > maksPisemny) {
  console.log("Błąd danych: punkty z części pisemnej poza zakresem.");
} else if (punktyPraktyczny < 0 || punktyPraktyczny > maksPraktyczny) {
  console.log("Błąd danych: punkty z części praktycznej poza zakresem.");
} else {

  // ── 2. Obliczenia ──
  const procentPisemny = (punktyPisemny / maksPisemny) * 100;
  const procentPraktyczny = (punktyPraktyczny / maksPraktyczny) * 100;

  const zdanyPisemny = procentPisemny >= PROG_PISEMNY;
  const zdanyPraktyczny = procentPraktyczny >= PROG_PRAKTYCZNY;
  const zdanyCaly = zdanyPisemny && zdanyPraktyczny;

  console.log(`Pisemna:     ${procentPisemny.toFixed(1)}%  (próg ${PROG_PISEMNY}%)  ${zdanyPisemny ? "zdana" : "niezdana"}`);
  console.log(`Praktyczna:  ${procentPraktyczny.toFixed(1)}%  (próg ${PROG_PRAKTYCZNY}%)  ${zdanyPraktyczny ? "zdana" : "niezdana"}`);

  // ── 3. Ocena według progów ──
  const sredni = (procentPisemny + procentPraktyczny) / 2;
  let ocena: number;

  if (sredni >= 91) {
    ocena = 6;
  } else if (sredni >= 81) {
    ocena = 5;
  } else if (sredni >= 71) {
    ocena = 4;
  } else if (sredni >= 51) {
    ocena = 3;
  } else if (sredni >= 31) {
    ocena = 2;
  } else {
    ocena = 1;
  }

  console.log("─".repeat(40));
  console.log(`Średni wynik: ${sredni.toFixed(1)}%`);
  console.log(`Ocena:        ${ocena}`);
  console.log(`Kwalifikacja: ${zdanyCaly ? "ZDANA" : "NIEZDANA"}`);

  // ── 4. Komentarz ──
  if (zdanyCaly && sredni >= 90) {
    console.log("Znakomity wynik — gratulacje!");
  } else if (zdanyCaly) {
    console.log("Kwalifikacja zdana, jest jeszcze pole do poprawy.");
  } else if (zdanyPisemny && !zdanyPraktyczny) {
    console.log("Do poprawy tylko część praktyczna.");
  } else if (!zdanyPisemny && zdanyPraktyczny) {
    console.log("Do poprawy tylko część pisemna.");
  } else {
    console.log("Do poprawy obie części.");
  }
}
wynik w konsoli
Wyniki: Marta Kowalska
────────────────────────────────────────
Pisemna:     80.0%  (próg 50%)  zdana
Praktyczna:  85.0%  (próg 75%)  zdana
────────────────────────────────────────
Średni wynik: 82.5%
Ocena:        5
Kwalifikacja: ZDANA
Kwalifikacja zdana, jest jeszcze pole do poprawy.

Trzy rzeczy warte podpatrzenia

TechnikaNa czym polega
Strażnicy na początku Wstępne warunki odrzucają błędy przewidziane w przykładzie. W pełnej walidacji trzeba również sprawdzić skończoność liczb, dopuszczalne wartości maksymalne i reguły punktacji.
Warunki w nazwanych zmiennych zdanyPisemny i zdanyPraktyczny liczymy raz, a używamy w czterech miejscach. Zmiana progu wymaga poprawki w jednej linii.
Deklaracja let ocena: number; przed drabinką Zmienna musi przeżyć wyjście z bloków if. Ostatni else gwarantuje, że zawsze dostanie wartość — inaczej kompilator zgłosiłby TS2454.

Sprawdź to sam

Zmień punktyPraktyczny na 10 i uruchom ponownie — zobaczysz komunikat o poprawce z części praktycznej. Potem ustaw obecnyNaObu na false i zwróć uwagę, że żadne obliczenie się nie wykona.

CZĘSTE BŁĘDY

Na co uważać

KodProblem
if (x = 5) Jeden znak równości to przypisanie, nie porównanie. Ma być ===. TypeScript zgłosi błąd, JavaScript wykonałby to bez słowa.
if (punkty >= 50); Średnik zaraz po nawiasie kończy instrukcję — blok poniżej wykona się zawsze.
if (a < b < c) Nie da się porównać trzech wartości naraz. Ma być a < b && b < c.
if (ocena === 5 || 6) Prawa strona to samo 6, czyli zawsze prawda. Ma być ocena === 5 || ocena === 6.
if (liczbaPunktow) przy 0 punktach Zero jest wartością fałszywą, więc warunek nie zadziała. Pisz if (liczbaPunktow !== undefined).
Drabinka bez else Gdy zmienna ma dostać wartość w każdej gałęzi, brak else to TS2454 — i słusznie.
ZADANIA

Zadania

ZAD 1Przewidź wynik★☆☆
zagadka.ts
const x = 10;

if (x > 5) {
  console.log("A");
} else if (x > 8) {
  console.log("B");
}

if (x > 5) {
  console.log("C");
}
if (x > 8) {
  console.log("D");
}
pokaż rozwiązanie
A
C
D

W pierwszej konstrukcji B jest nieosiągalne — else if sprawdza się tylko wtedy, gdy poprzedni warunek był fałszywy. W drugiej mamy dwie niezależne instrukcje if, więc obie się wykonują. To najważniejsza różnica między drabinką else if a osobnymi warunkami.

ZAD 2Klasyfikacja BMI★☆☆

Rozbuduj kalkulator BMI z lekcji 3: po obliczeniu wskaźnika wypisz kategorię według progów — poniżej 18,5 niedowaga, do 24,9 waga prawidłowa, do 29,9 nadwaga, powyżej otyłość. Użyj drabinki else if.

ZAD 3Cennik biletów★★☆

Bilet do kina kosztuje 28 zł. Zastosuj zniżki: dzieci do 6 lat wchodzą za darmo, uczniowie i studenci do 26 lat płacą 60% ceny, seniorzy od 65 lat płacą połowę. We wtorki wszyscy (poza dziećmi) dostają dodatkowe 5 zł zniżki, ale cena nie może spaść poniżej 10 zł. Wypisz wiek, dzień, zastosowaną zniżkę i kwotę do zapłaty.

pokaż przykładowe rozwiązanie
const CENA_PODSTAWOWA = 28;
const MIN_CENA = 10;

const wiek = 17;
const uczen = true;
const wtorek = true;

let cena: number;
let rodzajZnizki: string;

if (wiek < 6) {
  cena = 0;
  rodzajZnizki = "wstęp bezpłatny";
} else if (uczen && wiek <= 26) {
  cena = CENA_PODSTAWOWA * 0.6;
  rodzajZnizki = "uczniowska";
} else if (wiek >= 65) {
  cena = CENA_PODSTAWOWA * 0.5;
  rodzajZnizki = "senior";
} else {
  cena = CENA_PODSTAWOWA;
  rodzajZnizki = "brak";
}

if (wtorek && cena > 0) {
  cena = cena - 5;
  if (cena < MIN_CENA) {
    cena = MIN_CENA;
  }
  rodzajZnizki += " + wtorek";
}

console.log(`Wiek:       ${wiek}`);
console.log(`Zniżka:     ${rodzajZnizki}`);
console.log(`Do zapłaty: ${cena.toFixed(2)} zł`);

Zwróć uwagę na kolejność: najpierw ustalamy zniżkę podstawową w drabince (jedna z czterech), a dopiero potem, osobną instrukcją, doliczamy promocję wtorkową. To dwie niezależne decyzje, więc nie mogą być w jednej drabince.

ZAD 4Walidacja hasła★★☆

Sprawdź hasło zapisane w zmiennej i wypisz wszystkie niespełnione wymagania (nie tylko pierwsze): co najmniej 8 znaków, zawiera cyfrę, zawiera wielką literę, nie zawiera spacji. Na końcu wypisz ocenę siły hasła: słabe (0–1 spełnionych), średnie (2–3), mocne (4). Podpowiedź: zlicz spełnione wymagania w zmiennej.

pokaż wskazówki

Przejdź znaki pętlą. Cyfrę ASCII sprawdź przez znak >= "0" && znak <= "9". Wielką literę rozpoznaj przez znak === znak.toUpperCase() && znak !== znak.toLowerCase(). haslo.includes(" ") wykrywa zwykłą spację. To ćwiczenie warunków, nie kompletna ocena bezpieczeństwa hasła.

ZAD 5Kalkulator kosztów wyjazdu★★★

Napisz program liczący koszt wyjazdu klasowego. Dane: liczba uczniów, liczba nauczycieli, odległość w kilometrach, liczba noclegów. Zasady: autokar kosztuje 4,20 zł za kilometr, przy dystansie powyżej 300 km doliczana jest dieta kierowcy 250 zł. Nocleg to 90 zł od osoby, nauczyciele nocują bezpłatnie. Przy grupie 40 osób i większej cena noclegu spada do 80 zł. Wypisz rozbicie kosztów i kwotę przypadającą na jednego ucznia (zaokrągloną w górę do pełnych złotych — Math.ceil). Zadbaj o strażników: liczba uczniów musi być dodatnia, a nauczycieli co najmniej jeden.

pokaż szkielet rozwiązania
const uczniowie = 28;
const nauczyciele = 2;
const kilometry = 340;
const noclegi = 2;

if (uczniowie <= 0) {
  console.log("Błąd: brak uczniów.");
} else if (nauczyciele < 1) {
  console.log("Błąd: wymagany co najmniej jeden opiekun.");
} else {
  const osoby = uczniowie + nauczyciele;

  let kosztAutokaru = kilometry * 2 * 4.2;   // w obie strony
  if (kilometry > 300) {
    kosztAutokaru += 250;
  }

  const cenaNoclegu = osoby >= 40 ? 80 : 90;
  const kosztNoclegow = uczniowie * noclegi * cenaNoclegu;

  const razem = kosztAutokaru + kosztNoclegow;
  const naUcznia = Math.ceil(razem / uczniowie);

  console.log(`Autokar:    ${kosztAutokaru.toFixed(2)} zł`);
  console.log(`Noclegi:    ${kosztNoclegow.toFixed(2)} zł`);
  console.log(`Razem:      ${razem.toFixed(2)} zł`);
  console.log(`Na ucznia:  ${naUcznia} zł`);
}
PODSUMOWANIE

Co trzeba zapamiętać

  • Drabinka else if wykonuje dokładnie jedną gałąź — pierwszą pasującą.
  • Osobne instrukcje if są niezależne i mogą wykonać się wszystkie.
  • Przy progach liczbowych układaj warunki od najwyższego w dół.
  • Zmienna z let/const żyje tylko w swoim bloku klamrowym.
  • Zagnieżdżenia zastępuj strażnikami — najpierw odrzuć przypadki błędne.
  • Klamry piszemy zawsze, nawet przy jednej instrukcji.
  • Operator ? : wybiera wartość, if wybiera działanie.