← Wszystkie tematy W 89% ogłoszeń · 42 z 47 ogłoszeń frontend React

TypeScript

Pudełka z etykietą, co wolno do nich włożyć

TypeScript jest w 42 z 47 ogłoszeń. Seniorowi zadaje się pytania o modelowanie danych: unie, zawężanie, generyki i to, czego TypeScript nie sprawdzi.

Opanowane 0 z 6 pytań

Co piszą w ogłoszeniach

Scena pierwsza · typy

Pudełko z etykietą

Program to pudełka, do których wkładasz rzeczy. W zwykłym JavaScripcie pudełka nie mają etykiet: wejdzie wszystko, a pomyłka wychodzi dopiero, gdy ktoś otworzy pudełko, czyli u użytkownika. TypeScript przykleja na pudełko etykietę. Gdy włożysz coś nie tego, krzyczy od razu, jeszcze przy pisaniu kodu.

cukierki pusto
let cukierki = …
  1. Pisanie kodu
  2. Budowanie
  3. U użytkownika
Aplikacja liczy cukierki * 2 –

Wybierz rzecz z półki i włóż ją do pudełka.

Scena druga · unie i never

Sygnalizator, który nie zapomina

Ekran może być w kilku stanach: ładuje, gotowe albo błąd. To jest unia: jedna z kilku etykiet. Dla każdej musisz mieć obrazek. Co się stanie, gdy ktoś dopisze nowy stan offline i zapomni narysować dla niego obrazka?

 
Kliknij jeden ze stanów powyżej.

Pokliknij stany, potem dopisz „offline”.

Porównajmy

JavaScript czy TypeScript?

JavaScriptTypeScript
Pudełka Bez etykiet. Wejdzie wszystko.Typy dynamiczne, sprawdzane w runtime. Z etykietami. Wejdzie tylko to, co pasuje.Typy statyczne, sprawdzane przez kompilator.
Kiedy widać pomyłkę? Gdy ktoś otworzy pudełko.Błąd na produkcji: NaN, undefined is not a function. Od razu, przy pisaniu.Czerwone podkreślenie w edytorze, błąd tsc w CI.
Czy pilnuje w działającej aplikacji? Nie.Brak typów. Też nie! Etykiety znikają po zbudowaniu.Type erasure. Dane z API trzeba sprawdzić np. Zodem.
Zmiany w dużym kodzie Szukasz ręcznie, gdzie coś się zepsuło.Refaktor na ślepo. Kompilator pokazuje każde miejsce do poprawki.Bezpieczny refaktor, podpowiedzi w edytorze.
Cena Szybciej na start.Brak kroku kompilacji. Trzeba pisać etykiety.Więcej kodu, krzywa nauki przy generykach.

Etykieta

TypeScript to etykieta na pudełku. Krzyczy przy pisaniu, ale znika, zanim aplikacja trafi do użytkownika.

Never

„Never” to pudełko, do którego nic nie wolno włożyć. Gdy coś do niego trafi, znaczy to, że zapomniałeś o jakimś stanie.

Sprawdź się

Pytania z rozmów

Najpierw odpowiedz na głos, dopiero potem rozwiń odpowiedź.

  1. type vs interface: czym się różnią w praktyce?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: To dwa rodzaje etykiet. Etykietę „interface” można dokleić drugi raz i obie się połączą. Etykieta „type” umie za to opisać „albo to, albo tamto”.

    Na rozmowę: Oba opisują kształt obiektu. interface można rozszerzać przez extends i scalać przez ponowną deklarację (declaration merging), przydatne w bibliotekach i przy rozszerzaniu typów globalnych. type obsługuje unie, typy warunkowe, mapped types i tuple. W praktyce: type do unii i wyliczeń, interface do publicznych kształtów obiektów. Najważniejsze to być konsekwentnym w projekcie.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  2. Jak napisać generyczny komponent lub hook (np. lista z dowolnym typem elementu)?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Generyk to pudełko z pustą etykietą, na której piszesz dopiero wtedy, gdy wiesz, co włożysz. Raz to klocki, raz cukierki, a pudełko pilnuje, żeby się nie pomieszały.

    Na rozmowę: function List<T>({ items, renderItem, getKey }: { items: T[]; renderItem: (item: T) => ReactNode; getKey: (item: T) => string }). T wnioskuje się z items, więc renderItem dostaje poprawny typ bez rzutowania. Ograniczenia przez extends, np. <T extends { id: string }>, gdy potrzebuję pola id. Tak samo hooki: useFetch<T>(url): { data: T | undefined }.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  3. Union types i zawężanie (narrowing): jak modelować stany typu loading / success / error?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Sygnalizator ma kilka świateł. Gdy wiesz, że świeci „gotowe”, wiesz też, że w środku są cukierki. Gdy świeci „błąd”, w środku jest kartka z wiadomością.

    Na rozmowę: Discriminated union: { status: 'loading' } | { status: 'success'; data: T } | { status: 'error'; error: string }. Po sprawdzeniu status TS zawęża typ, więc data istnieje tylko w success i nie da się pokazać danych w stanie błędu. To lepsze niż trzy niezależne flagi isLoading/isError/data, które dopuszczają niemożliwe kombinacje. W switchu default z never wymusza obsłużenie każdego nowego stanu.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  4. unknown vs any vs never: kiedy którego używasz?

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: any to pudełko bez etykiety, do którego wszystko wejdzie i nikt nie sprawdza. unknown to paczka od nieznajomego: najpierw zajrzyj, co jest w środku. never to pudełko, do którego nic nie wolno włożyć.

    Na rozmowę: any wyłącza sprawdzanie i zaraża resztę kodu, więc unikam go (ewentualnie przy migracji). unknown to bezpieczny odpowiednik: przyjmie wszystko, ale przed użyciem trzeba zawęzić typ (typeof, instanceof, schemat Zod). Dobre dla danych z zewnątrz i bloku catch. never to typ bez wartości: wynik funkcji, która zawsze rzuca, i narzędzie do exhaustive check w switchu.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  5. Jak typować odpowiedzi z API, skoro TypeScript nie sprawdza ich w runtime? (Zod, walidacja)

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Dla przedszkolaka: Etykieta na pudełku znika, kiedy aplikacja trafia do ludzi. Paczkę z internetu trzeba więc sprawdzić ręcznie przy drzwiach, zanim wpuścisz ją do domu.

    Na rozmowę: Typy znikają po kompilacji (type erasure), więc „as User” na wyniku fetch to tylko obietnica. Na granicy systemu waliduję dane schematem, np. Zod: User = z.object({...}), a typ wyprowadzam przez z.infer<typeof User>. Wtedy jest jedno źródło prawdy, błędne dane wychodzą od razu w jednym miejscu, a nie jako undefined gdzieś w UI. Alternatywa to typy generowane z OpenAPI lub GraphQL.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
  6. Utility types: Partial, Pick, Omit, Record. Podaj realny przykład użycia.

    Moja odpowiedź

    Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

    Pokaż odpowiedź

    Na rozmowę: Partial<User> do formularza edycji lub patcha, gdzie każde pole jest opcjonalne. Pick<User, 'id' | 'name'> do lekkiego widoku listy. Omit<User, 'password'> do odpowiedzi publicznej albo Omit<ButtonProps, 'onClick'> przy wrapperze. Record<Status, string> do mapy etykiet: kompilator pilnuje, żeby każdy status miał tłumaczenie. Do tego ReturnType, Parameters i Awaited przy typach wyprowadzanych z funkcji.

    Umiem?
    Zapytaj Claude RozwińPrzepytaj mniePytania pogłębiające
Poziom wyżej

Wersja dla seniora

Tak wyglądają pytania na seniora i leada: nie ma jednej dobrej odpowiedzi, liczy się to, jak ważysz kompromisy i czy mówisz o skali, ryzyku i ludziach.

Przypadek 1

200 tysięcy linii JavaScriptu do przeniesienia na TypeScript strict

Aplikacja ma 200 tys. linii JS, 12 programistów i ciągły rozwój funkcji. Zarząd zgodził się na TypeScript, ale nie na zatrzymanie prac. Część zespołu chce od razu włączyć strict, część uważa, że TS ich spowolni.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy planujesz migrację przyrostową z mierzalnym postępem
  • Czy znasz ustawienia kompilatora, które to umożliwiają
  • Czy umiesz przekonać zespół i ustalić zasady

Odpowiedź seniora

Start: tsconfig z allowJs i checkJs: false, strict: true od pierwszego dnia, ale tylko dla plików .ts. Nowe pliki powstają w TS, a zmieniane przy okazji pracy są przenoszone. Dzięki temu nie ma długu „luźnego TS”, który trzeba będzie zaostrzać drugi raz.

Kolejność migracji: najpierw warstwy, od których zależy najwięcej kodu (klient API, modele domenowe, utils), bo dają typy reszcie. Typy z API generuję z OpenAPI, zamiast pisać ręcznie. Tam, gdzie typ jest trudny, dopuszczam jawne // @ts-expect-error z komentarzem i ticketem zamiast any. Zakaz nowych any pilnuje ESLint (@typescript-eslint/no-explicit-any jako error dla nowych plików).

Postęp mierzę skryptem: procent plików TS i liczba ts-expect-error, widoczne na dashboardzie. Typecheck w CI jest wymagany od pierwszego dnia. Zespołowi daję krótkie warsztaty, wzorcowe pliki i parowanie przy pierwszych migracjach. Po 3 miesiącach checkJs dla pozostałych plików, żeby złapać najgroźniejsze błędy.

Typowe wpadki

  • Włączenie strict globalnie i 8 tysięcy błędów na start
  • Masowe dodanie any, żeby się kompilowało
  • Migracja jako osobny projekt, który zatrzymuje rozwój

Dopytają o

  • Co zrobisz z bibliotekami bez typów?
  • Jak migrujesz komponenty React z propTypes?
  • Jak przekonasz osobę, która uważa, że TS spowalnia?
Zapytaj Claude Rozwiń caseZagraj interviewera
Przypadek 2

Typy współdzielone z backendem, które ciągle się rozjeżdżają

Frontend ma ręcznie pisane interfejsy odpowiedzi API. Backend w Kotlinie zmienia pola, a frontend dowiaduje się o tym z błędów produkcyjnych typu „cannot read property of undefined”. Zespoły są w różnych repozytoriach.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy znasz podejścia contract-first i code-first
  • Czy rozumiesz, że typy nie chronią w runtime
  • Czy umiesz wpiąć to w proces CI obu zespołów

Odpowiedź seniora

Ręczne interfejsy to tylko obietnica. Wybieram kontrakt jako źródło prawdy: backend publikuje specyfikację OpenAPI generowaną z kodu, a frontend generuje z niej typy i klienta (openapi-typescript, orval) w CI. Zmiana kontraktu, która psuje frontend, wychodzi jako błąd kompilacji w PR, a nie na produkcji.

Na granicy w runtime waliduję krytyczne odpowiedzi schematem (zod generowany z OpenAPI albo ręcznie dla kluczowych zasobów) i loguję niezgodności do Sentry, zamiast od razu wywracać UI. Backend dostaje w CI sprawdzanie zgodności wstecznej specyfikacji (oasdiff), więc usunięcie pola jest jawną decyzją.

Gdyby oba systemy były w TypeScripcie i w jednym monorepo, rozważyłbym tRPC albo wspólny pakiet schematów zod. Przy Kotlinie najrozsądniejszy jest OpenAPI.

Typowe wpadki

  • „Dopiszemy as User i będzie dobrze”
  • Walidacja każdej odpowiedzi tak ostra, że drobna zmiana wywala cały ekran
  • Brak ustaleń z backendem, tylko narzędzie po stronie frontu

Dopytają o

  • Co zrobisz z polami opcjonalnymi, które backend zawsze wysyła?
  • Jak wersjonować kontrakt, gdy są dwie aplikacje mobilne?
  • Gdzie walidować: w kliencie HTTP czy w komponencie?
Zapytaj Claude Rozwiń caseZagraj interviewera
Przypadek 3

Publiczna biblioteka komponentów i breaking change w typach

Utrzymujesz bibliotekę komponentów używaną przez 15 aplikacji. Chcesz zmienić typ propsa variant z string na unię literałów i usunąć stary prop color. Ostatnia podobna zmiana zablokowała trzy zespoły na tydzień.

Zanim rozwiniesz: powiedz na głos, jak byś to rozwiązał, i nazwij co najmniej jeden kompromis.

Moje rozwiązanie

Zapisuje się samo w tej przeglądarce. Kopię zrobisz na stronie Notatki.

Pokaż, czego szuka rekruter, i modelową odpowiedź

Co sprawdza rekruter

  • Czy traktujesz typy jako część publicznego API
  • Czy znasz techniki deprecjacji w TypeScript
  • Czy umiesz to wdrożyć organizacyjnie

Odpowiedź seniora

Zmiana typu z string na unię to breaking change, nawet jeśli runtime się nie zmienia, bo psuje kompilację konsumentów. Wydaję ją w wersji major, a wcześniej w minor dodaję nowe API obok starego: variant przyjmuje unię | (string & {}) z ostrzeżeniem w dev dla nieznanych wartości, a color jest oznaczony @deprecated w JSDoc, więc edytor go przekreśla.

Do migracji dostarczam codemod (jscodeshift albo ts-morph), który zamienia color na variant w kodzie konsumentów, plus changeset z instrukcją. Przed wydaniem sprawdzam wpływ: buduję wszystkie 15 aplikacji z nową wersją w CI (canary release w npm z tagiem next). Eksportowane typy pilnuję narzędziem API Extractor, które pokazuje różnice w publicznym API w PR.

Ustalam politykę: deprecation trwa co najmniej jeden minor i 4 tygodnie, a majory wychodzą zbiorczo, nie co tydzień.

Typowe wpadki

  • Zmiana typów w wersji patch, „bo runtime ten sam”
  • Usunięcie propsa bez okresu przejściowego
  • Brak testu biblioteki na prawdziwych konsumentach

Dopytają o

  • Jak testujesz typy biblioteki (tsd, expectTypeOf)?
  • Co zrobisz, gdy jeden zespół nie może migrować przez kwartał?
  • Jak generujesz dokumentację propsów z typów?
Zapytaj Claude Rozwiń caseZagraj interviewera

Skróty klawiszowe

/
szukaj tematu
Enter
w wyszukiwarce: otwórz pierwszy wynik
N
notatki do tematu
[ ]
poprzedni / następny temat
G potem T
lista tematów
G potem P
powtórka
G potem N
wszystkie notatki
D
jasny / ciemny motyw
?
ta ściąga
Spacja, 1, 2, 3
w powtórce: pokaż, oceń

Pod każdym pytaniem są też skróty do Claude: rozwinięcie tematu, próbna rozmowa i ocena Twojej odpowiedzi z notatki.