Czy w 2026 roku warto jeszcze uczyć się JavaScriptu przed TypeScriptem?

Sławomir Plamowski 17 min czytania
frontend javascript kariera nauka-programowania poczatkujacy pytania-rekrutacyjne typescript

92% ofert pracy dla frontend developerów w Polsce wymaga znajomości TypeScript. Jednocześnie 100% tych ofert wymaga znajomości JavaScript. To nie przypadek - TypeScript jest nadzbiorem JS, co oznacza że każdy kod JavaScript jest poprawnym kodem TypeScript, ale nie odwrotnie. Pytanie "JavaScript czy TypeScript?" jest więc źle postawione. Prawdziwe pytanie brzmi: czy warto uczyć się fundamentów JS przed przejściem na TS, czy można je pominąć?

To pytanie dzieli społeczność programistów. Jedni twierdzą, że w 2026 roku nauka czystego JS to strata czasu - lepiej od razu pisać z typami. Drudzy argumentują, że bez zrozumienia mechanizmów JS, TypeScript staje się magiczną skrzynką, która "jakoś działa". Oba stanowiska mają racjonalne argumenty.

W tym artykule przedstawię obie perspektywy, pokażę konkretne przykłady gdzie znajomość JS ratuje tyłek nawet w projektach TypeScript, i dam praktyczne rekomendacje dla różnych ścieżek kariery. Bez dogmatów - tylko fakty i doświadczenie.

Fundamentalne pytanie - czym właściwie jest TypeScript?

Odpowiedź w 30 sekund

TypeScript to nadzbiór JavaScript z opcjonalnym statycznym typowaniem. Każdy poprawny kod JS jest poprawnym kodem TS. TypeScript kompiluje się do JavaScript - przeglądarki i Node.js wykonują JS, nie TS. Główna wartość to wykrywanie błędów podczas pisania kodu (nie w runtime) i lepsze narzędzia deweloperskie. TypeScript nie zmienia jak JavaScript działa - dodaje warstwę sprawdzania typów na etapie kompilacji.

Odpowiedź w 2 minuty

Tu robi się ciekawie, bo to rozróżnienie jest kluczowe dla całej dyskusji. TypeScript nie jest "nowym JavaScript" ani "lepszym JavaScript". To JavaScript z dodatkiem - systemem typów, który istnieje tylko podczas developmentu.

Pokażę na przykładzie:

// Kod TypeScript
function greet(name: string): string {
    return `Hello, ${name}!`;
}

const message: string = greet("Anna");

Po kompilacji do JavaScript:

// Ten sam kod po kompilacji - typy zniknęły
function greet(name) {
    return `Hello, ${name}!`;
}

const message = greet("Anna");

Widzisz różnicę? Wszystkie adnotacje typów (: string) zniknęły. W runtime nie ma żadnej różnicy - przeglądarka wykonuje identyczny kod. Typowanie istnieje tylko podczas pisania i kompilacji.

To prowadzi do ważnego wniosku: wszystkie mechanizmy JavaScript (hoisting, closure, prototypy, event loop, this) działają identycznie w TypeScript. TS nie zmienia jak JS działa - tylko dodaje statyczną analizę na wierzchu.

flowchart LR subgraph "Development" A[Kod TypeScript] --> B[Kompilator TSC] B --> C{Błędy typów?} C -->|Tak| D[Popraw błędy] D --> A end subgraph "Runtime" C -->|Nie| E[Kod JavaScript] E --> F[Przeglądarka/Node.js] end style A fill:#e3f2fd style B fill:#fff3e0 style E fill:#e8f5e9 style F fill:#c8e6c9

Ten diagram pokazuje kluczową rzecz: TypeScript istnieje tylko po lewej stronie. W momencie gdy kod trafia do przeglądarki lub Node.js, jest już czystym JavaScript. Jeśli nie rozumiesz JS, nie rozumiesz co tak naprawdę robi twoja aplikacja.

Argumenty za nauką JavaScript przed TypeScript

Rozumienie "co jest pod spodem"

Wzorzec, który obserwuję u kandydatów na rozmowach: programista pisze w TypeScript od początku, kod działa, testy przechodzą. Pada pytanie: "Dlaczego ten callback zachowuje dostęp do zmiennej z zewnętrznej funkcji?" Cisza. "Co to jest closure?" Cisza.

TypeScript nie uczy closure - zakłada że je znasz. Nie uczy hoistingu - zakłada że wiesz dlaczego var zachowuje się inaczej niż let. Nie uczy event loop - zakłada że rozumiesz asynchroniczność.

// Klasyczny problem z closure - ten kod pojawi się na rozmowie
for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}
// Wynik: 3, 3, 3 - nie 0, 1, 2

// Dlaczego? Closure zamyka REFERENCJĘ do i, nie wartość
// var ma function scope, więc jest jedna zmienna i dla całej pętli
// Gdy setTimeout się wykonuje, pętla już się skończyła, i === 3

// Rozwiązanie 1: let ma block scope
for (let i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}
// Wynik: 0, 1, 2

// Rozwiązanie 2: IIFE tworzy nowy scope
for (var i = 0; i < 3; i++) {
    ((j) => {
        setTimeout(() => console.log(j), 100);
    })(i);
}
// Wynik: 0, 1, 2

TypeScript nie pomoże ci zrozumieć dlaczego pierwszy przykład wypisuje "3, 3, 3". Typy są poprawne - i to number, callback to () => void. Kompilator jest zadowolony. Problem leży w mechanizmie JavaScript, który TS nie zmienia.

Więcej o tym i innych fundamentalnych konceptach JavaScript znajdziesz w naszym artykule o 15 najtrudniejszych pytaniach rekrutacyjnych z JavaScript.

Debugowanie wymaga znajomości JS

Gdy coś nie działa w aplikacji TypeScript, debugujesz JavaScript. DevTools w przeglądarce pokazują JS (nawet z source maps, widzisz transpilowany kod). Stack trace odnosi się do JS. Błędy runtime to błędy JS.

// Kod TypeScript - wygląda bezpiecznie
interface User {
    name: string;
    age: number;
}

async function fetchUser(id: number): Promise<User> {
    const response = await fetch(`/api/users/${id}`);
    return response.json(); // TypeScript ufa że to User
}

const user = await fetchUser(123);
console.log(user.name.toUpperCase()); // Potential runtime error!

TypeScript mówi: "user.name to string, możesz wywołać toUpperCase()". Ale co jeśli API zwróci { name: null } lub { username: "Anna" } (inne pole)? TypeScript nie sprawdza runtime - ufa twojej deklaracji. Błąd Cannot read property 'toUpperCase' of null to błąd JavaScript, który musisz umieć zdebugować.

Ekosystem zakłada znajomość JS

Dokumentacja React, Vue, Angular - często pokazuje przykłady w JS. Stack Overflow - większość odpowiedzi w JS. Biblioteki open source - kod źródłowy często w JS. Legacy kod w firmie - prawie na pewno JS.

Nawet w 2026 roku, ogromna większość istniejącego kodu to JavaScript. Będziesz go czytać, debugować, migrować. Bez znajomości JS staniesz przed ścianą.

Argumenty za rozpoczęciem od TypeScript

Mniej złych nawyków do oduczenia

Argument przeciwny: jeśli zaczniesz od JS, nauczysz się pisać kod bez typów. Potem będziesz musiał się przestawiać. Lepiej od razu budować nawyki pisania z typami.

// Typowy kod JS początkującego
function processUser(user) {
    // Co to jest user? Jakie ma pola?
    // Czy name to string? Może array?
    return user.name.toUpperCase();
}

// Od razu TS wymusza myślenie o strukturze
interface User {
    id: number;
    name: string;
    email: string;
}

function processUser(user: User): string {
    // Jasne co wchodzi, jasne co wychodzi
    return user.name.toUpperCase();
}

Zaczynając od TS, od razu myślisz o typach, interfejsach, kontraktach między funkcjami. To dobre nawyki, które w czystym JS trzeba świadomie praktykować (np. przez JSDoc).

IDE experience jest nieporównywalnie lepszy

Visual Studio Code z TypeScript to zupełnie inne doświadczenie niż z czystym JS. Autouzupełnianie wie co możesz wywołać na zmiennej. Refaktoryzacja działa pewnie. Błędy widać od razu, nie po uruchomieniu.

Dla początkującego to ogromna różnica. Zamiast szukać w dokumentacji "jakie metody ma string", widzisz je w podpowiedziach. Zamiast runtime error "undefined is not a function", widzisz czerwoną linię podczas pisania.

Rynek pracy mówi jasno

Przejrzyj oferty pracy na JustJoinIT czy NoFluffJobs - TypeScript jest wszędzie. Nowe projekty w React, Angular, Vue startują z TypeScript. Node.js backend coraz częściej w TS. Nawet projekty "JavaScript" często mają // @ts-check lub JSDoc dla typów.

Argument pragmatyczny: ucz się tego, za co płacą.

Ścieżka kompromisowa - jak to połączyć

Moja rekomendacja dla początkujących

Wzorzec, który mi się sprawdził przy mentoringu junior developerów:

flowchart TB subgraph "Tydzień 1-2: Fundamenty JS" A[Typy i konwersje] --> B[Scope i closure] B --> C[this i kontekst] C --> D[Prototypy] end subgraph "Tydzień 3-4: Asynchroniczność" E[Callbacks] --> F[Promise] F --> G[async/await] G --> H[Event loop] end subgraph "Tydzień 5-6: TypeScript" I[Podstawowe typy] --> J[Interfejsy i type] J --> K[Generyki] K --> L[Konfiguracja tsconfig] end D --> E H --> I style A fill:#e3f2fd style E fill:#e3f2fd style I fill:#e8f5e9

Nie chodzi o zostanie ekspertem JS przed dotknięciem TS. Chodzi o zrozumienie fundamentów, które TS wykorzystuje ale nie uczy. 2-4 tygodnie na JS, potem przejście na TS i już pozostanie przy nim.

Konkretnie - co musisz znać z JS

Zamiast "naucz się JavaScript", dam konkretną listę tematów. Każdy z nich pojawia się na rozmowach rekrutacyjnych, nawet na stanowiska TypeScript:

Typy i konwersje

// Musisz rozumieć te wyniki
console.log(typeof null);           // "object" - historyczny bug
console.log(typeof undefined);      // "undefined"
console.log(typeof []);             // "object" - tablice to obiekty
console.log([] == false);           // true - type coercion
console.log([] === false);          // false - strict equality
console.log("5" + 3);               // "53" - konkatenacja
console.log("5" - 3);               // 2 - konwersja do number

Scope i hoisting

// Dlaczego to działa?
sayHello();  // "Hello!" - function hoisting

function sayHello() {
    console.log("Hello!");
}

// A to nie?
sayGoodbye();  // TypeError: sayGoodbye is not a function

var sayGoodbye = function() {
    console.log("Goodbye!");
};
// var jest hoistowany jako undefined, funkcja nie

this w różnych kontekstach

const obj = {
    name: "Anna",
    greet: function() {
        console.log(`Hello, ${this.name}`);
    },
    greetArrow: () => {
        console.log(`Hello, ${this.name}`);  // this !== obj!
    }
};

obj.greet();        // "Hello, Anna"
obj.greetArrow();   // "Hello, undefined" - arrow function nie ma własnego this

const greet = obj.greet;
greet();            // "Hello, undefined" - utracony kontekst
greet.call(obj);    // "Hello, Anna" - explicit binding

Te mechanizmy działają identycznie w TypeScript. TS nie ostrzeże cię przed greet() bez kontekstu - typy są poprawne, problem jest w runtime behavior.

Konkretnie - co musisz znać z TypeScript

Po fundamentach JS, te tematy TS są kluczowe:

Podstawowe typy i adnotacje

// Typy prymitywne
let name: string = "Anna";
let age: number = 25;
let isActive: boolean = true;

// Tablice
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];

// Tuple - tablica o stałej długości i typach
let person: [string, number] = ["Anna", 25];

// Enum
enum Status {
    Pending,
    Active,
    Completed
}

// any vs unknown - kluczowa różnica
let anything: any = "hello";
anything.nonExistentMethod();  // Brak błędu kompilacji!

let something: unknown = "hello";
something.toUpperCase();  // Błąd! Musisz najpierw sprawdzić typ
if (typeof something === "string") {
    something.toUpperCase();  // OK po type guard
}

Interface vs Type

// Interface - rozszerzalny, dla obiektów
interface User {
    id: number;
    name: string;
}

interface Admin extends User {
    permissions: string[];
}

// Type - bardziej elastyczny
type ID = string | number;  // Union - interface tego nie może

type Point = {
    x: number;
    y: number;
};

type Point3D = Point & { z: number };  // Intersection

// Praktyczna różnica: declaration merging
interface Config {
    debug: boolean;
}

interface Config {  // Łączy się z poprzednim!
    verbose: boolean;
}

// type Config = { debug: boolean };
// type Config = { verbose: boolean };  // Błąd! Duplicate identifier

Generyki - klucz do reusable kodu

// Bez generyków - tracimy informację o typie
function firstElement(arr: any[]): any {
    return arr[0];
}

const num = firstElement([1, 2, 3]);  // typ: any (!)

// Z generykami - zachowujemy typ
function firstElementTyped<T>(arr: T[]): T | undefined {
    return arr[0];
}

const num2 = firstElementTyped([1, 2, 3]);     // typ: number
const str = firstElementTyped(["a", "b"]);      // typ: string

// Generyki z ograniczeniami
interface HasLength {
    length: number;
}

function logLength<T extends HasLength>(item: T): void {
    console.log(item.length);
}

logLength("hello");      // OK - string ma length
logLength([1, 2, 3]);    // OK - array ma length
logLength(123);          // Błąd! number nie ma length

Więcej o TypeScript dla początkujących znajdziesz w naszym dedykowanym artykule: Pytania rekrutacyjne z TypeScript dla początkujących.

Klasyczny problem - migracja JS do TS

Na rozmowach rekrutacyjnych często pojawia się zadanie: "Dodaj typy do tego kodu JavaScript". To testuje zrozumienie obu języków.

Kod źródłowy (JavaScript)

// api.js - typowy kod JS do zmigrowania
async function fetchUsers(options) {
    const { page = 1, limit = 10, filter } = options || {};

    let url = `/api/users?page=${page}&limit=${limit}`;
    if (filter) {
        url += `&filter=${encodeURIComponent(filter)}`;
    }

    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return {
        users: data.users,
        total: data.total,
        hasMore: page * limit < data.total
    };
}

// Użycie
fetchUsers({ page: 2, filter: "active" })
    .then(result => {
        console.log(result.users);
    });

Rozwiązanie - TypeScript z pełnymi typami

// api.ts - ten sam kod z typami

// Najpierw definiujemy typy danych
interface User {
    id: number;
    name: string;
    email: string;
    status: "active" | "inactive";
}

// Typy dla opcji funkcji
interface FetchUsersOptions {
    page?: number;
    limit?: number;
    filter?: string;
}

// Typy dla odpowiedzi API
interface ApiResponse {
    users: User[];
    total: number;
}

// Typy dla wyniku funkcji
interface FetchUsersResult {
    users: User[];
    total: number;
    hasMore: boolean;
}

// Funkcja z pełnymi typami
async function fetchUsers(options?: FetchUsersOptions): Promise<FetchUsersResult> {
    const { page = 1, limit = 10, filter } = options ?? {};

    let url = `/api/users?page=${page}&limit=${limit}`;
    if (filter) {
        url += `&filter=${encodeURIComponent(filter)}`;
    }

    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    // Tutaj zakładamy że API zwraca poprawne dane
    // W produkcji warto dodać walidację runtime (np. zod)
    const data: ApiResponse = await response.json();

    return {
        users: data.users,
        total: data.total,
        hasMore: page * limit < data.total
    };
}

// Teraz IDE wie dokładnie co zwraca funkcja
fetchUsers({ page: 2, filter: "active" })
    .then(result => {
        // result.users to User[], nie any[]
        result.users.forEach(user => {
            console.log(user.name);  // Autouzupełnianie działa!
        });
    });

Zwróć uwagę na kilka rzeczy:

Interfejsy dokumentują strukturę danych - bez czytania implementacji wiesz co funkcja przyjmuje i zwraca. To jest główna wartość TypeScript.

Zamiana || na ?? - w TypeScript często używamy nullish coalescing (??) zamiast logical OR (||), bo ?? sprawdza tylko null/undefined, a || traktuje 0 i "" jako falsy.

Typ "active" | "inactive" - literal types pozwalają ograniczyć wartości do konkretnych stringów. To silniejsze niż string.

Błędy przy migracji - czego unikać

// ❌ ŹLE - any wszędzie
async function fetchUsers(options: any): Promise<any> {
    // To kompiluje się, ale nie daje żadnych korzyści TS
}

// ❌ ŹLE - za szerokie typy
interface FetchUsersResult {
    users: object[];  // Co to jest "object"? Nic nie wiadomo
    total: number;
    hasMore: boolean;
}

// ❌ ŹLE - brak obsługi undefined
function processUser(user: User) {
    console.log(user.name.toUpperCase());  // Co jeśli user jest undefined?
}

// ✅ DOBRZE - defensive typing
function processUser(user: User | undefined) {
    if (!user) {
        throw new Error("User is required");
    }
    console.log(user.name.toUpperCase());
}

// Lub z optional chaining
function processUserSafe(user?: User) {
    console.log(user?.name?.toUpperCase() ?? "Unknown");
}

Co rekruterzy sprawdzają w 2026

Pytania o JavaScript (nawet na stanowisko TS)

Na rozmowach nadal padają klasyczne pytania o JS. Rekruterzy wiedzą, że TypeScript to warstwa nad JavaScript - jeśli nie rozumiesz fundamentów, twój kod będzie działał "przypadkiem".

Typowe pytania:

  • Wyjaśnij czym jest closure i podaj przykład użycia
  • Jak działa this w różnych kontekstach?
  • Co to jest event loop i jak działa kolejność wykonania microtasks vs macrotasks?
  • Jaka jest różnica między == a ===?
  • Wytłumacz hoisting dla var, let, const i funkcji

Kandydaci, którzy robią wrażenie to ci, którzy potrafią wyjaśnić nie tylko "co" ale "dlaczego". Nie tylko "let ma block scope" ale "let wprowadzono w ES6 żeby rozwiązać problemy z var w pętlach i closure".

Pytania o TypeScript

Oprócz JS, rekruterzy sprawdzają praktyczną znajomość TS:

  • Kiedy użyjesz interface a kiedy type?
  • Co to są generyki i kiedy ich używasz?
  • Jaka jest różnica między any a unknown?
  • Jak działa keyof i typeof?
  • Co to są utility types (Partial, Required, Pick, Omit)?
// Przykład pytania praktycznego - utility types
interface User {
    id: number;
    name: string;
    email: string;
    password: string;
    createdAt: Date;
}

// Stwórz typ dla tworzenia usera (bez id i createdAt)
type CreateUserDTO = Omit<User, "id" | "createdAt">;

// Stwórz typ dla aktualizacji (wszystko opcjonalne, bez password)
type UpdateUserDTO = Partial<Omit<User, "password">>;

// Stwórz typ tylko do wyświetlania (bez password)
type UserPublic = Pick<User, "id" | "name" | "email">;

Live coding - mieszanka JS i TS

Zadania praktyczne często łączą znajomość obu. Na przykład:

"Napisz funkcję debounce z pełnymi typami TypeScript."

To wymaga zrozumienia closure (JS) i generyków (TS):

function debounce<T extends (...args: any[]) => any>(
    func: T,
    wait: number
): (...args: Parameters<T>) => void {
    let timeout: ReturnType<typeof setTimeout> | null = null;

    return function(this: ThisParameterType<T>, ...args: Parameters<T>) {
        if (timeout) {
            clearTimeout(timeout);
        }

        timeout = setTimeout(() => {
            func.apply(this, args);
            timeout = null;
        }, wait);
    };
}

// Użycie - TypeScript wie jakie argumenty przyjmuje zdebouncowana funkcja
const debouncedSearch = debounce((query: string) => {
    console.log(`Searching for: ${query}`);
}, 300);

debouncedSearch("hello");  // OK
debouncedSearch(123);      // Błąd! Argument typu 'number' nie jest przypisywalny

To rozwiązanie pokazuje zaawansowane typy TS (Parameters, ReturnType, ThisParameterType) ale również wymaga zrozumienia jak działa this, apply i closure w JavaScript.

Praktyczne zadania do sprawdzenia

Przed rozmową rekrutacyjną sprawdź czy potrafisz odpowiedzieć na te pytania:

Zadanie 1: Przewidź output

console.log(typeof typeof 1);
Odpowiedź
"string"

typeof 1 zwraca "number" (string). typeof "number" zwraca "string".

Zadanie 2: Napisz typ dla tej funkcji

function merge(target, ...sources) {
    return Object.assign(target, ...sources);
}
Odpowiedź
function merge<T extends object, U extends object[]>(
    target: T,
    ...sources: U
): T & U[number] {
    return Object.assign(target, ...sources);
}

Zadanie 3: Co jest nie tak z tym kodem?

interface Config {
    timeout: number;
    retries: number;
}

function createConfig(overrides: Partial<Config>): Config {
    return {
        timeout: 1000,
        retries: 3,
        ...overrides
    };
}

const config = createConfig({ timeout: undefined });
console.log(config.timeout);  // ???
Odpowiedź

Wynik to undefined, nie 1000. Spread nadpisuje wartości domyślne nawet jeśli są undefined. TypeScript to przepuści bo Partial<Config> dopuszcza undefined. Poprawne rozwiązanie:

function createConfig(overrides: Partial<Config>): Config {
    return {
        timeout: overrides.timeout ?? 1000,
        retries: overrides.retries ?? 3
    };
}

Zadanie 4: Zaimplementuj type-safe event emitter

// Użycie powinno wyglądać tak:
const emitter = createEmitter<{
    login: { userId: string };
    logout: { reason: string };
}>();

emitter.on("login", (data) => {
    console.log(data.userId);  // TypeScript wie że to string
});

emitter.emit("login", { userId: "123" });  // OK
emitter.emit("login", { reason: "test" }); // Błąd!
Odpowiedź
type EventMap = Record<string, any>;

interface Emitter<T extends EventMap> {
    on<K extends keyof T>(event: K, handler: (data: T[K]) => void): void;
    emit<K extends keyof T>(event: K, data: T[K]): void;
}

function createEmitter<T extends EventMap>(): Emitter<T> {
    const handlers: Partial<Record<keyof T, ((data: any) => void)[]>> = {};

    return {
        on<K extends keyof T>(event: K, handler: (data: T[K]) => void) {
            if (!handlers[event]) {
                handlers[event] = [];
            }
            handlers[event]!.push(handler);
        },
        emit<K extends keyof T>(event: K, data: T[K]) {
            handlers[event]?.forEach(handler => handler(data));
        }
    };
}

Podsumowanie - moja rekomendacja

Po latach pracy z obiema technologiami i mentoringu dziesiątek developerów, moja rekomendacja jest taka:

Naucz się fundamentów JavaScript (2-4 tygodnie). Nie musisz być ekspertem. Musisz rozumieć: typy i konwersje, scope i closure, this, prototypy (podstawy), asynchroniczność (Promise, async/await, event loop).

Potem przejdź na TypeScript i już przy nim zostań. Pisz wszystkie nowe projekty w TS. Wracaj do dokumentacji JS gdy coś jest niejasne.

Nie pomijaj fundamentów JS nawet jeśli zaczynasz od TS. Debugowanie, code review, legacy kod, dokumentacja - wszędzie będziesz potrzebować tej wiedzy.

Czy można zacząć od TypeScript? Technicznie tak. Ale będziesz jak kierowca, który nie wie jak działa silnik - dopóki wszystko działa, jest OK. Gdy coś się zepsuje, staniesz bezradny.


Zobacz też


Chcesz więcej pytań rekrutacyjnych?

Ten artykuł to wprowadzenie do tematu. Jeśli przygotowujesz się do rozmowy rekrutacyjnej, potrzebujesz systematycznej nauki z setkami pytań i odpowiedzi.

Nasze fiszki zawierają pytania z JavaScript, TypeScript, React i innych technologii w formacie "30 sekund / 2 minuty" - idealnym do przygotowania przed rozmową.

Zobacz wszystkie fiszki do nauki →

Lub sprawdź darmowy podgląd:


Artykuł powstał na podstawie doświadczeń z prowadzenia rozmów rekrutacyjnych i mentoringu junior developerów w polskich firmach technologicznych.

Chcesz więcej pytań rekrutacyjnych?

To tylko jeden temat z naszego kompletnego przewodnika po rozmowach rekrutacyjnych. Uzyskaj dostęp do 800+ pytań z 13 technologii.

Kup pełny dostęp Zobacz bezpłatny podgląd
Powrót do blogu

Zostaw komentarz

Pamiętaj, że komentarze muszą zostać zatwierdzone przed ich opublikowaniem.