To jest darmowy podgląd

To jest próbka 15 pytań z naszej pełnej kolekcji 33 pytań rekrutacyjnych. Uzyskaj pełny dostęp do wszystkich pytań ze szczegółowymi odpowiedziami i przykładami kodu.

Kup pełny dostęp

Podstawy TypeScript

Czym jest TypeScript i jakie korzyści płyną z jego używania w porównaniu do standardowego JavaScript?

TypeScript to język programowania, który stanowi nadzbiór JavaScript. Oznacza to, że każdy poprawny kod JavaScript jest również poprawnym kodem TypeScript, przy czym TypeScript wprowadza dodatkowe funkcjonalności, takie jak statyczne typowanie oraz zaawansowaną obsługę obiektowości. Główne korzyści z używania TypeScript to:

  • Statyczne typowanie: Pozwala na wychwycenie wielu błędów już na etapie kompilacji, co zwiększa stabilność i bezpieczeństwo kodu.
  • Lepsza czytelność kodu: Wprowadzenie typów i interfejsów ułatwia zrozumienie struktury projektu, szczególnie w dużych aplikacjach.
  • Wsparcie nowoczesnych funkcji: Umożliwia korzystanie z najnowszych funkcji ECMAScript, które są następnie kompilowane do JavaScript kompatybilnego z wybranymi środowiskami.
  • Rozbudowane narzędzia: Dzięki integracji z edytorami i IDE, takimi jak Visual Studio Code czy IntelliJ IDEA, możliwe jest korzystanie z inteligentnego podpowiadania kodu oraz refaktoryzacji.

Dalsze informacje na temat TypeScript można znaleźć w oficjalnej dokumentacji TypeScript oraz na artykułach na Wikipedii (polska wersja).

↑ Powrót na górę

Jak zainstalować i skonfigurować kompilator TypeScript w projekcie?

Aby rozpocząć pracę z TypeScript, należy zainstalować kompilator. Najprostszym sposobem jest użycie npm (Node Package Manager). Przykładowo:

  1. Instalacja globalna (umożliwia korzystanie z polecenia tsc w dowolnym miejscu):

    npm install -g typescript
    
  2. Instalacja lokalna (zalecana w projektach, aby wersja kompilatora była zależna od projektu):

    npm install --save-dev typescript
    
  3. Inicjalizacja konfiguracji: Po instalacji warto wygenerować plik tsconfig.json, który jest głównym narzędziem konfiguracyjnym TypeScript:

    npx tsc --init
    

    Plik tsconfig.json pozwala m.in. określić docelową wersję ECMAScript, dołączane pliki, zakres błędów oraz dodatkowe opcje kompilatora.

Więcej informacji na temat konfiguracji znajdziesz w dokumentacji TypeScript dotyczącej konfiguracji.

↑ Powrót na górę

Jakie są główne różnice między TypeScript a JavaScript?

Podstawowe różnice pomiędzy TypeScript a JavaScript obejmują:

  • Typowanie:

    • TypeScript: Wprowadza statyczne typowanie, co umożliwia deklarację typów dla zmiennych, funkcji i obiektów.
    • JavaScript: Jest językiem dynamicznie typowanym, gdzie typy są określane w czasie wykonywania.
  • Narzędzia i wsparcie IDE:

    • TypeScript: Dzięki statycznej analizie kodu, edytory zapewniają zaawansowane funkcje takie jak podpowiedzi, automatyczne uzupełnianie, refaktoryzację oraz wykrywanie błędów już podczas pisania kodu.
    • JavaScript: Choć również posiada wsparcie w nowoczesnych edytorach, brak statycznych typów ogranicza możliwości w tym zakresie.
  • Nowoczesne funkcjonalności:

    • TypeScript: Pozwala na korzystanie z najnowszych funkcji ECMAScript oraz dodatkowych mechanizmów obiektowych (np. interfejsów, typów generycznych), które są następnie transpilowane do kompatybilnej wersji JavaScript.
    • JavaScript: Bezpośrednio używa jedynie funkcjonalności dostępnych w specyfikacji języka, co może wiązać się z koniecznością stosowania dodatkowych polyfilli lub bibliotek w starszych środowiskach.

Dla dogłębnej analizy różnic warto zapoznać się z artykułami porównawczymi, np. porównanie TypeScript i JavaScript na blogu lub w polskiej wersji Wikipedii.

↑ Powrót na górę

Typy danych i zmienne

Jakie są podstawowe typy danych dostępne w TypeScript?

W TypeScript dostępne są następujące typy danych:

  • number – reprezentuje liczby, zarówno całkowite, jak i zmiennoprzecinkowe.
  • string – reprezentuje ciągi znaków.
  • boolean – reprezentuje wartość logiczną true lub false.
  • null i undefined – reprezentują odpowiednio brak wartości i niezdefiniowaną wartość.
  • symbol – unikalny identyfikator, używany przy tworzeniu unikalnych właściwości obiektów.
  • bigint – służy do reprezentacji bardzo dużych liczb całkowitych.
  • any – wyłącza statyczne sprawdzanie typów, pozwalając na dowolną wartość.
  • unknown – bezpieczniejsza alternatywa dla any, wymaga dodatkowego sprawdzenia typu przed użyciem.
  • void – najczęściej używany jako typ zwracany przez funkcje, które nie zwracają żadnej wartości.
  • never – reprezentuje typ funkcji, które nigdy nie kończą działania (np. funkcje rzucające wyjątek).

Więcej informacji na temat podstawowych typów dostępnych w TypeScript znajdziesz w oficjalnej dokumentacji TypeScript – Basic Types.

↑ Powrót na górę

Czym jest wnioskowanie typów (type inference) i jakie są jego zalety?

TypeScript potrafi automatycznie wywnioskować typy zmiennych na podstawie przypisanych wartości. Dzięki temu nie musimy jawnie określać typu dla każdej zmiennej, co zwiększa czytelność kodu i zmniejsza nadmiarowość anotacji typów. Zalety wnioskowania typów to:

  • Redukcja ilości kodu – mniejsza liczba jawnych deklaracji.
  • Bezpieczeństwo typów – kompilator nadal jest w stanie sprawdzać poprawność typów, co zapobiega wielu potencjalnym błędom.
  • Lepsza czytelność – kod jest bardziej zwięzły i łatwiejszy do utrzymania.

Przykład:

let wiek = 30; // TypeScript wnioskuje, że 'wiek' ma typ number
wiek = 31;   
// wiek = "trzydzieści jeden"; // spowoduje błąd kompilacji, ponieważ typ string jest niezgodny z typem number

Więcej o wnioskowaniu typów znajdziesz w oficjalnej dokumentacji TypeScript – Type Inference.

↑ Powrót na górę

W jaki sposób definiować typ enum i w jakich sytuacjach warto go stosować?

enum umożliwia definiowanie zestawu nazwanych stałych, co zwiększa czytelność i utrzymanie kodu. W TypeScript enums mogą być numeryczne (domyślne) lub łańcuchowe (string enums).
Przykład numerycznego enum:

enum Kolor {
  Czerwony,   // domyślnie 0
  Zielony,    // 1
  Niebieski,  // 2
}
let wybranyKolor: Kolor = Kolor.Zielony;

Przykład enum z wartościami łańcuchowymi:

enum Kierunek {
  Północ = "POLNOC",
  Południe = "POLUDNIE",
  Wschód = "WSCHOD",
  Zachód = "ZACHOD"
}
let kierunekPodrozy: Kierunek = Kierunek.Wschód;

Enums są szczególnie przydatne, gdy zestaw dozwolonych wartości jest z góry ustalony i niezmienny, np. dni tygodnia, stany w aplikacji lub kierunki ruchu.

Więcej informacji na temat enums znajdziesz w dokumentacji TypeScript – Enums.

↑ Powrót na górę

Funkcje i klasy

Jak definiować funkcje w TypeScript z uwzględnieniem określania typów argumentów i zwracanego typu?

W TypeScript funkcje definiujemy podobnie jak w JavaScript, ale dodając adnotacje typów dla argumentów oraz typu zwracanego. Przykład definicji funkcji:

function dodaj(a: number, b: number): number {
  return a + b;
}

Tutaj:

  • Typy number przy argumentach a i b określają, że funkcja przyjmuje liczby.
  • Adnotacja : number po nawiasach funkcji oznacza typ zwracanego wyniku.

Materiał do pogłębienia tematu:
Oficjalny podręcznik TypeScript – Functions

↑ Powrót na górę

Jakie mechanizmy wsparcia oferuje TypeScript dla programowania obiektowego (klasy, dziedziczenie, interfejsy)?

TypeScript rozszerza możliwości JavaScript o pełne wsparcie dla programowania obiektowego. Obejmuje to między innymi:

  • Klasy: Pozwalają definiować szablony obiektów. Możemy w nich definiować właściwości, metody oraz konstruktory.
  • Dziedziczenie: Klasy mogą rozszerzać inne klasy przy użyciu słowa kluczowego extends, co umożliwia ponowne wykorzystanie i rozszerzenie funkcjonalności.
  • Interfejsy: Umożliwiają definiowanie kontraktów, które muszą spełniać klasy lub obiekty, co poprawia spójność i typowanie kodu.

Przykład klasy z interfejsem:

interface IPunkt {
  x: number;
  y: number;
}

class Punkt implements IPunkt {
  constructor(public x: number, public y: number) {}
}

class KolorowyPunkt extends Punkt {
  constructor(x: number, y: number, public kolor: string) {
    super(x, y);
  }
}

Materiał do pogłębienia tematu:
Oficjalny podręcznik TypeScript – Klasy

↑ Powrót na górę

Jak zrealizować przeciążanie funkcji (function overloading) w TypeScript?

TypeScript umożliwia definiowanie wielu sygnatur funkcji, co nazywamy przeciążaniem funkcji. Najpierw deklarujemy kilka sygnatur, a następnie implementujemy funkcję, która obsługuje wszystkie warianty. Przykład:

// Definicje przeciążone
function przetworz(tekst: string): string;
function przetworz(liczba: number): number;

// Implementacja funkcji
function przetworz(param: string | number): string | number {
  if (typeof param === "string") {
    return param.toUpperCase();
  } else {
    return param * 2;
  }
}

// Użycie
console.log(przetworz("hello")); // "HELLO"
console.log(przetworz(5));       // 10

Materiał do pogłębienia tematu:
Oficjalny podręcznik TypeScript – Przeciążanie funkcji

↑ Powrót na górę

Zaawansowane typy i funkcje

Jak działają generyki w TypeScript i dlaczego są ważnym narzędziem w tworzeniu elastycznych komponentów?

Generyki w TypeScript umożliwiają definiowanie funkcji, klas czy interfejsów, które mogą operować na danych o różnych typach, przy zachowaniu pełnej kontroli nad typami w czasie kompilacji. Pozwala to na tworzenie elastycznych i wielokrotnego użytku komponentów, które są jednocześnie bezpieczne typowo. Dzięki generykom można uniknąć powielania kodu oraz minimalizować błędy związane z nieprawidłowym użyciem typów, co przekłada się na bardziej wydajny i czytelny kod.

Źródła:

↑ Powrót na górę

Czym jest typ unknown i kiedy warto go używać?

Typ unknown został wprowadzony jako bezpieczniejsza alternatywa dla typu any. Podobnie jak any może reprezentować dowolną wartość, jednakże operacje na zmiennych typu unknown wymagają uprzedniej weryfikacji typu lub użycia mechanizmów zawężających typ (ang. type narrowing). Stosowanie typu unknown jest zalecane, gdy nie mamy pewności co do typu wartości, ale chcemy zachować pełną kontrolę nad jej przetwarzaniem, co zwiększa bezpieczeństwo aplikacji.

Źródła:

↑ Powrót na górę

Jak implementować typy warunkowe (conditional types) oraz mapowanie typów (mapped types) w praktyce?

Typy warunkowe (conditional types):
Pozwalają na wybór jednego z dwóch typów na podstawie spełnienia określonego warunku. Składnia przypomina konstrukcję warunkową if-else w typach. Umożliwia dynamiczne określanie typu na podstawie relacji między typami wejściowymi.

Mapowanie typów (mapped types):
Służą do transformowania typów poprzez iterację po kluczach danego typu i modyfikację przypisanych do nich typów. Dzięki temu można w łatwy sposób tworzyć nowe typy na bazie istniejących, np. poprzez oznaczanie wszystkich właściwości jako opcjonalne lub wymagane.

Implementacja tych mechanizmów umożliwia tworzenie bardziej dynamicznych i abstrakcyjnych definicji typów, co jest szczególnie przydatne w dużych projektach, gdzie zachowanie spójności typów jest kluczowe.

Źródła:

↑ Powrót na górę

Moduły i systemy modułów

Jakie sposoby importu i eksportu modułów oferuje TypeScript?

TypeScript wspiera standardowe sposoby importu i eksportu modułów zgodne z ECMAScript. Oferuje między innymi:

  • Import/eksport nazwany – umożliwia eksport wielu elementów z modułu:

    // module.ts
    export const foo = 'foo';
    export function bar() { }
    
    // innyPlik.ts
    import { foo, bar } from './module';
    
  • Eksport domyślny – pozwala wyeksportować jeden element jako domyślny:

    // module.ts
    export default function baz() { }
    
    // innyPlik.ts
    import baz from './module';
    
  • Eksport całego modułu – umożliwia ponowne eksportowanie wszystkich elementów z danego modułu:

    export * from './module';
    
  • Dynamiczny import – pozwala na asynchroniczne ładowanie modułów:

    async function loadModule() {
      const module = await import('./module');
      module.bar();
    }
    

Linki referencyjne:

↑ Powrót na górę

W jaki sposób TypeScript integruje się z narzędziami bundlerów (np. Webpack, Rollup)?

TypeScript doskonale integruje się z narzędziami bundlerów za pomocą następujących mechanizmów:

  • Transpilacja – TypeScript kompiluje kod do JavaScript, który jest następnie przetwarzany przez bundlery.
  • Loadery – przy integracji z Webpack stosuje się m.in. ts-loader lub babel-loader z odpowiednimi presetami, które pozwalają na bezproblemową transpilację TypeScript podczas bundlingu.
  • Wtyczki dla Rollup – Rollup może korzystać z wtyczki @rollup/plugin-typescript, która obsługuje pliki TypeScript i umożliwia konfigurację specyficzną dla danego projektu.

Dzięki tym narzędziom możliwe jest wykorzystanie zalet statycznej analizy i typowania oferowanych przez TypeScript, przy jednoczesnym korzystaniu z zaawansowanych technik optymalizacji kodu przez bundlery.

Linki referencyjne:

↑ Powrót na górę

Jak zarządzać ścieżkami modułów przy pomocy aliasów (path mapping) w konfiguracji TypeScript?

Path mapping pozwala na tworzenie aliasów dla długich lub skomplikowanych ścieżek importu, co znacząco poprawia przejrzystość kodu. Aby skonfigurować aliasy, należy:

  1. Ustawić baseUrl oraz zdefiniować paths w pliku tsconfig.json:

    {
      "compilerOptions": {
        "baseUrl": "./",
        "paths": {
          "@components/*": ["src/components/*"],
          "@utils/*": ["src/utils/*"]
        }
      }
    }
    
  2. Stosować aliasy w importach:

    import { MyComponent } from '@components/MyComponent';
    import { helper } from '@utils/helper';
    
  3. Konfiguracja bundlera – Aby aliasy działały również przy budowaniu kodu za pomocą bundlera (np. Webpack), należy skonfigurować odpowiednie aliasy w pliku konfiguracyjnym bundlera.

Linki referencyjne:

↑ Powrót na górę

Chcesz więcej pytań?

Uzyskaj dostęp do 800+ pytań z 13 technologii - JavaScript, React, TypeScript, Node.js, SQL i więcej. Natychmiastowy dostęp na 30 dni.

Kup pełny dostęp za 49,99 zł