← Wszystkie tematy

Pytania rekrutacyjne TypeScript z odpowiedziami

Typy, generyki, zawężanie, typy narzędziowe i warunkowe, konfiguracja i typowanie Reacta.

225 pytań na rozmowę rekrutacyjną z tematu TypeScript z odpowiedziami i wyjaśnieniami - poziomy Junior, Middle i Senior. Przykładowe pytania, testy online i zadania z kodu.

Pytania według poziomu

Przykładowe pytania

Kilka pytań z każdego poziomu z poprawną odpowiedzią i wyjaśnieniem.

TypeScript · Junior

  1. Czym jest TypeScript?

    Poprawna odpowiedź: Nadzbiorem JavaScriptu ze statycznym typowaniem, kompilowanym do JS

    Każdy poprawny JS jest prawie zawsze poprawnym TS. Typy są sprawdzane podczas kompilacji, a potem usuwane: w runtime działa zwykły JavaScript i nie ma tam sprawdzania typów. Dlatego dane zewnętrzne (API, formularze) nadal waliduje się w runtime - np. przez Zod.

  2. Czy TypeScript sprawdza typy podczas działania programu?

    Poprawna odpowiedź: Nie: typy są usuwane podczas kompilacji; w runtime działa zwykły JS

    TypeScript to narzędzie czasu programowania. Jeśli API zwróci null zamiast obiektu, typy cię nie uratują. Do sprawdzeń w runtime używa się typeof/instanceof i bibliotek schematów (Zod, Valibot), z których można też wyprowadzić typy TS.

  3. Czym unknown różni się od any?

    Poprawna odpowiedź: Z unknown nic nie zrobisz bez zawężenia, a any wyłącza sprawdzanie

    any wyłącza typowanie i „zaraża” wszystko, czego dotknie. unknown to bezpieczny odpowiednik: wartość może być czymkolwiek, ale użyć jej można dopiero po sprawdzeniu (typeof x === 'string'). Dla danych z JSON.parse i catch (e) właściwym wyborem jest unknown.

  4. Co oznacza typ never?

    Poprawna odpowiedź: Typ wartości, która nie może istnieć: funkcja nigdy nie zwraca sterowania

    never to typ pusty. Zwracają go funkcje, które zawsze rzucają błąd lub działają w nieskończoność. Pojawia się też, gdy unia jest w pełni zawężona - na tym opierają się wyczerpujące sprawdzenia w switch. void oznacza, że funkcja się kończy, ale jej wynik nie jest używany.

Wszystkie 75 pytań z odpowiedziami →

TypeScript · Middle

  1. Co oznacza <T extends { id: string }> w generyku?

    Poprawna odpowiedź: Ograniczenie: T musi mieć co najmniej właściwość id: string

    Ograniczenie pozwala bezpiecznie odwoływać się do item.id wewnątrz funkcji, zachowując pełny typ T w wyniku. Można przekazać dowolny obiekt z odpowiednim id i innymi polami. Klasy i dziedziczenie nie mają z tym nic wspólnego.

  2. Jak otypować getProp(obj, key), by wynik zależał od klucza?

    Poprawna odpowiedź: function getProp<T, K extends keyof T>(obj: T, key: K): T[K]

    K extends keyof T dopuszcza tylko istniejące klucze, a dostęp indeksowany T[K] daje dokładny typ wartości: getProp(user, 'age') → number. Wersja z any traci typowanie, a string przepuszcza literówki.

  3. Co robi typ warunkowy T extends string ? 'text' : 'other'?

    Poprawna odpowiedź: Wybiera jeden z typów w zależności od tego, czy T jest przypisywalny do string

    Typy warunkowe to „operator trójargumentowy” na poziomie typów. Razem z infer pozwalają wyciągać części typów. Zastosowane do unii rozkładają się na każdy człon (distributive conditional types).

  4. Co robi infer w type ElementType<T> = T extends (infer U)[] ? U : never?

    Poprawna odpowiedź: Deklaruje zmienną typu U, którą TS wywnioskuje z dopasowania do wzorca

    infer stosuje się tylko w części extends typu warunkowego: TS dopasowuje T do wzorca i „przechwytuje” potrzebną część. ElementType<string[]> → string. Tak działają ReturnType, Parameters i Awaited.

Wszystkie 75 pytań z odpowiedziami →

TypeScript · Senior

  1. Czy przy strictFunctionTypes można przypisać (x: Dog) => void do zmiennej typu (x: Animal) => void?

    Poprawna odpowiedź: Nie: parametry funkcji są sprawdzane kontrawariantnie

    Zmienna obiecuje przyjąć dowolne Animal, a funkcja umie obsłużyć tylko Dog - wywołanie z Cat by ją zepsuło. Dlatego podtypowanie po parametrze działa w odwrotną stronę: (x: Animal) => void można przypisać tam, gdzie oczekiwane jest (x: Dog) => void, ale nie odwrotnie.

  2. Dlaczego strictFunctionTypes nie działa dla metody zadeklarowanej jako handle(x: Dog): void?

    Poprawna odpowiedź: Parametry w składni metody są sprawdzane biwariantnie pod kątem zgodności

    Biwariantność metod zachowano, by wiele wbudowanych typów (np. Array<T>) pozostało zgodnych. Jeśli zamiast tego zadeklarujesz właściwość-funkcję handle: (x: Dog) => void, sprawdzenie będzie ścisłe. Dlatego dla callbacków w interfejsach często wybiera się składnię właściwości.

  3. Czym jest ToArray<string | number>, jeśli type ToArray<T> = T extends any ? T[] : never?

    Poprawna odpowiedź: string[] | number[]

    Typ warunkowy nad „gołym” parametrem typu rozkłada się na unię: warunek jest stosowany do każdego członu osobno. To distributive conditional type - na nim zbudowane są Exclude i Extract.

  4. Jak wyłączyć rozkładanie typu warunkowego na unię?

    Poprawna odpowiedź: Opakować obie strony w krotkę: [T] extends [U] ? X : Y

    Rozkład następuje tylko wtedy, gdy sprawdzany typ jest „gołym” parametrem. Krotka [T] czyni go złożonym, więc unia jest sprawdzana w całości: [string | number] extends [string] → false. Nie ma do tego ustawienia kompilatora.

Wszystkie 75 pytań z odpowiedziami →

Testy łączone z tym tematem

Pytania z kilku tematów naraz - jak na rozmowie rekrutacyjnej na konkretne stanowisko.

Zadania z kodu

Napisz rozwiązanie prosto w przeglądarce, a testy od razu je sprawdzą. Klasyka rozmów rekrutacyjnych: debounce, throttle, deepClone, Promise.all, EventEmitter, cache LRU i inne.

Otwórz zadania →