IT/программирование

Что реально спрашивают на собеседовании фронтенд-стажёра

Разбор реального технического собеседования фронтенд-стажёра: вопросы по React, TypeScript, NestJS и live coding. Чек-лист для подготовки.

Что реально спрашивают на собеседовании фронтенд-стажёра

Что реально спрашивают на собеседовании фронтенд-стажёра

Команда ZUB-AI посмотрела запись реального технического собеседования на позицию стажёра full-stack разработчика с уклоном во фронтенд. Формат простой и честный: без постановочных сцен, с реальными паузами, ошибками кандидата и живой реакцией интервьюера. За две недели до записи этого ролика было отсмотрено около 60 заявок и проведено 16 собеседований — то есть перед нами не разовая история, а выжимка из целой воронки найма.

Кому это полезно? Если вы готовитесь к позиции junior/intern frontend или fullstack, это почти готовый чек-лист вопросов. Если вы сами нанимаете стажёров — это пример структуры интервью, которую можно взять за основу. Главный вывод одним предложением: сильная теория и хорошие пет-проекты перевешивают провал на алгоритмах, но полное отсутствие прогресса в live coding — это всё равно тревожный звонок.

Дальше разберём собеседование по блокам: проекты, React, TypeScript,… (48:43) ▶ 48:43

Дальше разберём собеседование по блокам: проекты, React, TypeScript, бэкенд-интеграция, NestJS и живое кодирование. В конце — практический чек-лист и наши наблюдения о том, где подходы к найму сходятся, а где расходятся.

Почему проекты важнее резюме

Первое, на что смотрит интервьюер — не список технологий в резюме, а конкретные пет-проекты. Логика простая: знания, которые не применялись на практике, забываются или остаются поверхностными. Кандидат в разборе — это человек с опытом около 5 лет с перерывами, который начал путь с моддинга игр («стимка»), а серьёзно погрузился в разработку курсе на третьем.

Из его портфолио выделяются три вещи:

Иллюстрация из видео (03:50) ▶ 03:50

  • Проект авторизации с access/refresh токенами через Redis, всё самописное кроме JWT-библиотеки.
  • Микросервисная архитектура через Consul: регистрация портов, конфигурация через dependency injection, общение сервисов через единый инстанс Redis. Отдельно пришлось городить собственный фильтр исключений — потому что exception при передаче между сервисами сериализуется через раз.
  • Образовательная платформа про кино, где бэкенд почти готов, а фронтенд ещё не начат. Первая версия была признана самим кандидатом неудачной — «полная лажа» с проблемами транзакций, поэтому проект переписывался заново.

Самая сложная задача, которую выделил кандидат — ротация JWT-токена при обновлении страницы. Токен не обновлялся из-за того, что interceptor работает не на том уровне жизненного цикла, что рендеринг компонента. Мелочь, а голову сломать можно легко — знакомая история для любого, кто городил свою авторизацию с нуля.

Вывод для читателя: если у вас нет fullstack-опыта, но есть один доведённый до конца проект с нетривиальной архитектурой — это весит больше, чем десять недоделанных клонов Netflix.

React: что спрашивают и где обычно спотыкаются

Кандидат оценил себя на 5 из 10 по React, объяснив это перерывами в практике до полугода. Это честная и разумная самооценка — здесь важнее не цифра, а готовность признать пробелы.

Вопросы, которые звучали:

Иллюстрация из видео (20:17) ▶ 20:17

  • Чем React/Vue лучше чистого JS — актуальность данных, клиентский рендеринг, Virtual DOM, управление состоянием через хуки.
  • Опыт со стейт-менеджерами: Zustand («любимый, потому что простой»), Redux (знает всю экосистему), но Context API — слабее.
  • useMemo vs useCallback — тут кандидат ответил корректно: useMemo кеширует результат вычисления при неизменных зависимостях, useCallback сохраняет стабильную ссылку на функцию между рендерами, чтобы React.memo действительно работал, а не перерендеривал компонент зря.
  • Классический кейс: родитель передаёт функцию дочернему компоненту через React.memo. Без useCallback дочерний компонент всё равно перерендерится — потому что при каждом рендере родителя создаётся новая ссылка на функцию, и memo это ловит как изменение пропсов.
  • Виртуализация списков — концепция, где на экране рендерятся только видимые элементы (условно 10 из 1000), а при скролле верхние элементы размонтируются, нижние монтируются, расчёт идёт через estimated size и индексы. Кандидат объяснил идею верно, но признался, что саму библиотеку (речь про react-virtualized) до конца не разбирал.
  • Условия ре-рендера компонента: изменение состояния, изменение контекста при подписке, ре-рендер родителя — даже если пропсы дочернего компонента не изменились.

Заметьте: почти все вопросы — не про синтаксис, а про то, почему React ведёт себя так, а не иначе. Это типичный признак сильного технического интервью — синтаксис гуглится за секунду, а понимание механизма ре-рендеров — нет.

TypeScript: структурная типизация и антипаттерны

Самооценка кандидата — 6-7 из 10, интервьюер отметил, что кандидат себя занизил. Разберём, что спрашивали.

Первый блок — зачем вообще нужен TypeScript. (27:54) ▶ 27:54

Первый блок — зачем вообще нужен TypeScript. Классический пример: в JS "2" + 2 даёт строку "22", потому что слабая динамическая типизация позволяет складывать что угодно со всем подряд. TypeScript ловит такие вещи на этапе компиляции, а не в рантайме у пользователя.

Второй момент — структурная типизация. TypeScript сравнивает типы по набору полей, а не по имени типа. Если два интерфейса содержат одинаковые поля, объект технически может имплементировать оба одновременно. Это принципиально отличается от номинальной типизации (например, в C#), где типы сравниваются по имени объявления, а не по структуре.

Дальше — живой разбор Omit и Exclude прямо в редакторе кода. Кандидат сначала перепутал их назначение, пытаясь применить Exclude к полям объекта. Совместно с интервьюером разобрались: Exclude работает с union-типами (убирает часть вариантов из объединения), а для исключения полей объекта нужен именно Omit. Разница небольшая на бумаге, но путаница между ними — частая ошибка даже у людей с опытом.

Антипаттерны, которые назвал кандидат:

  • any — ломает всю систему типов, потому что отключает проверку целиком.
  • as (type assertion) — по сути говорит компилятору «доверься мне», хотя компилятор может быть прав, а разработчик — нет.
  • Discriminated union без exhaustive check — ситуация, когда добавляется новый вариант в union, а обработку в switch забыли добавить, и TypeScript это не подсвечивает, если явно не проверять полноту через never.

Отдельно разобрали, почему вместо any лучше использовать unknown: unknown не даёт напрямую вызывать методы или обращаться к полям без предварительной проверки типа (type guard). Кандидат перечислил основные type guards: typeof, instanceof, проверку свойства через in, а также проверки через классы и прототипы.

Дженерики кандидат честно назвал своей слабой темой, но привёл рабочий пример —… (12:53) ▶ 12:53

Дженерики кандидат честно назвал своей слабой темой, но привёл рабочий пример — интерфейс пагинации с generic-полем items, который позволяет использовать одну структуру и для массива пользователей, и для массива продуктов, не дублируя код.

Взаимодействие фронтенда с бэкендом

Здесь вопросы уже не про «знаешь ли ты React», а про то, как ты реально организуешь работу с API в проекте.

  • URL бэкенда хранится через переменные окружения (.env) — базовая гигиена, но спрашивают не зря: удивительно часто встречаются захардкоженные адреса в коде.
  • Кандидат использовал паттерн «papka servis» отдельно от FSD-архитектуры для организации API-запросов — то есть слой сервисов вынесен отдельно от фичей и сущностей.
  • Инструмент — TanStack Query, с флагами enabled, isLoading, isFetching для управления состоянием загрузки и условными запросами.
  • Обсуждали Next.js: серверные и клиентские компоненты. Базовое определение кандидат дал верно — серверные рендерятся на сервере, клиентские на клиенте. А вот сложный кейс — синхронизация серверных данных с TanStack Query через infinite scroll, с использованием параметра initialData — вызвал затруднение. Кандидат честно признался, что почти не работал с этим параметром на практике.

Это нормальная картина для стажёрского уровня: база закрыта, а продвинутые кейсы синхронизации SSR-данных с клиентским кешированием — это уже следующая ступень.

NestJS и работа с бэкендом

  • Guards — использовались для проверки ролей пользователя, что-то вроде RBAC-подхода (role-based access control).
  • Interceptors — применялись для перехвата запросов со статусом 401 и обработки логики повторной авторизации.
  • Декораторы — использовались повсеместно, они и есть значительная часть архитектуры NestJS.
  • Способы взаимодействия клиент-сервер: HTTP/REST — на практике, GraphQL и gRPC — только в теории, без реального опыта применения.
  • Prisma: назначение ORM объяснено верно — упрощение работы с SQL, миграции, типизация моделей базы данных. Миграции нужны, чтобы отслеживать изменения схемы БД в командной разработке и не ловить рассинхронизацию между разработчиками, которые параллельно меняют структуру таблиц.

Live coding: где кандидат просел

Первое задание было небольшим и концептуальным: почему при двух подряд вызовах setCount(count + 1) счётчик увеличивается только на 1, а не на 2. Кандидат правильно определил суть проблемы — замыкание захватывает устаревшее значение count на момент рендера — и предложил решение через функциональное обновление состояния (setCount(prev => prev + 1)). Чистый плюс, отвечает быстро и по делу.

А вот дальше начинается самая показательная часть всего интервью — алгоритмическая задача на поиск пересечения двух массивов без дубликатов.

Путь кандидата к решению:

  1. Первая идея — вложенный цикл, то есть решение за O(n²). Рабочее, но неоптимальное.
  2. После нескольких прямых подсказок интервьюера кандидат переходит к идее использовать словарь (Map): сначала заполнить его элементами первого массива, затем пройтись по второму и проверять наличие элемента в словаре.
  3. По пути — целая серия мелких ошибок: путаница с индексами, лишние условия, неправильная проверка дубликатов через includes на результирующем массиве вместо проверки самого словаря.
  4. Итоговое рабочее решение получено только благодаря нескольким прямым подсказкам, а не самостоятельно.
  5. Интервьюер в финале показал более элегантный вариант — через Set вместо Map. По производительности идентично, но короче кода и уникальность значений гарантируется структурой данных сама по себе, без ручных проверок.

Важный нюанс: интервьюер прямо говорит, что не ставит алгоритмические задачи в приоритет при итоговой оценке, потому что такую задачу можно решить через ChatGPT за десять секунд. Гораздо важнее ход мысли и честность попытки — видно ли, что человек реально думает, а не подглядывает в телефон под столом. При этом отмечается: кандидата легко «спалить» на использовании ChatGPT прямо во время звонка — по характерным паузам, панике при смене формулировки вопроса и специфическому звуку набора текста.

Итоговая оценка и что это значит для вас

Финальный вердикт интервьюера: сильные знания React и TypeScript, впечатляющий практический опыт для уровня стажёра — включая работу с микросервисами, что для junior-позиции скорее редкость. При этом явный провал по алгоритмической задаче — кандидат не дошёл до рабочего решения даже с явными подсказками.

И тут интервьюер сам ставит интересный вопрос: насколько вообще актуален формат классического технического собеседования на фоне развития ИИ-инструментов. Если алгоритмическую задачу можно решить через ChatGPT за минуту, а архитектурные решения в реальных проектах кандидат принимал сам — что важнее оценивать на входе?

Что делать прямо сейчас: чек-лист подготовки

Если вы готовитесь к похожему собеседованию, вот конкретный список, который стоит закрыть за одну-две недели:

  1. Соберите один законченный пет-проект с нетривиальной частью — авторизация с ротацией токенов, микросервисы, любая асинхронная логика с реальными подводными камнями. Один доведённый проект сильнее пяти брошенных.
  2. Прогоните механику ре-рендеров React руками: напишите компонент с React.memo, добавьте дочерний компонент с функцией-пропсом, проверьте разницу с useCallback и без него в React DevTools Profiler.
  3. Разберите разницу между Omit и Exclude, Pick и Extract — на живых примерах в редакторе, а не по памяти. Пропишите руками по 2-3 варианта использования каждого.
  4. Проговорите вслух, зачем нужен unknown вместо any, и приведите пример type guard для каждого способа: typeof, instanceof, in.
  5. Порешайте 10-15 простых задач на массивы и строки с акцентом на Map/Set — не ради запоминания решений, а чтобы не путаться в базовой логике под давлением. Особое внимание — на разницу производительности O(n²) vs O(n) и на то, когда Set удобнее Map.
  6. Подготовьте историю про самую сложную техническую проблему, которую вы решали — с деталями, а не общими словами. Именно такие истории интервьюеры запоминают лучше всего.
  7. Не полагайтесь на ChatGPT во время звонка — если задача рабочая, ход мысли важнее финального кода, а попытку скрыть подглядывание распознают быстро.

Что мы заметили

Разбирая это собеседование, мы обратили внимание на несколько закономерностей, которые встречаются в свежих материалах по найму фронтенд-разработчиков в целом.

Первое — почти везде приоритет смещается с алгоритмических задач в сторону практического опыта и архитектурных решений. Формат «два часа лайвкодинга на LeetCode» постепенно уступает место разбору реальных пет-проектов и обсуждению конкретных технических решений в них.

Второе — есть расхождение в подходах к оценке кандидата. Более мягкий подход (как в этом собеседовании) допускает провал по алгоритмам, если остальная база сильная — теория, архитектурное мышление, честность в ответах. Более консервативный взгляд, который встречается в других разборах интервью, всё же считает алгоритмическую секцию отсекающей: не решил задачу — не прошёл, независимо от остальных ответов. Какой подход правильный — зависит от команды и от того, что реально будет делать стажёр в первые месяцы: писать бизнес-логику или оптимизировать highload-сервисы.

Третье — тема ИИ-инструментов на собеседованиях становится центральной, а не побочной. Раньше вопрос был «списывает кандидат или нет», сейчас вопрос смещается в сторону «а что вообще имеет смысл проверять, если решение задачи занимает у ChatGPT десять секунд». Это меняет саму структуру интервью: меньше внимания финальному коду, больше — процессу мышления и умению объяснить архитектурные решения своими словами.

Четвёртое — структурная типизация TypeScript и разница между Omit/Exclude всплывают в разборах постоянно. Похоже, это одна из самых частых точек путаницы даже у разработчиков с реальным продакшн-опытом, а не только у новичков.

Обобщение

Собеседование в разборе — не идеальный кандидат и не провальный, а вполне рабочий средний случай: сильная теория, реальный практический опыт с непростыми штуками вроде микросервисов и токен-ротации, и совершенно ожидаемая просадка на классической алгоритмике под стрессом живого звонка. Именно такие интервью и стоит разбирать — не выдуманные идеальные ответы из статей, а живой процесс с ошибками, подсказками и честными «я не знаю».

Если вы готовитесь к похожему собеседованию на позицию фронтенд-стажёра или fullstack-джуниора — не тратьте всю подготовку на LeetCode. Разберите один свой проект до мелочей, закройте пробелы в TypeScript-утилитах и механике React-рендеров, и потренируйтесь объяснять ход мысли вслух — именно это, судя по всему, сейчас решает больше, чем идеально написанный алгоритм за 20 минут.

Использованные видео

Хотите такой же разбор для своего видео?

ZUB-AI проанализирует видео с YouTube, RuTube или VK и пришлёт структурированный отчёт. Первый анализ — бесплатно.

Попробовать ZUB-AI →