TypeScript: Полный гайд по подготовке к собеседованию

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему TypeScript — must have для современного разработчика?

Если вы открыли эту статью, значит, вы уже знаете, что TypeScript — это не просто «надстройка над JavaScript», а полноценный инструмент, который спасает нервные клетки и продакшн-сервера. На собеседованиях в 2025 году знание TypeScript проверяют почти в 80% вакансий middle+ уровня. И речь не о том, чтобы написать const a: number = 5. Интервьюеры хотят видеть понимание системы типов, дженериков и умение проектировать безопасную архитектуру.

В этой статье мы разберём самые частые вопросы на собеседовании по TypeScript, которые реально задают в топовых компаниях. Вы получите не только теорию, но и примеры кода TypeScript, которые можно сразу использовать в pet-проектах. Поехали!

1. База: типы, интерфейсы и разница между ними

Первый блок вопросов — фундаментальный. Интервьюер хочет убедиться, что вы не путаете type и interface.

Когда использовать type, а когда interface?

Классический вопрос. Запомните простое правило:

  • Interface — для объектов, которые можно расширять (declaration merging). Используйте для API, DTO, пропсов компонентов.
  • Type — для объединений (union), пересечений, примитивов и кортежей.

Пример из реального собеседования:

// Interface — расширяем
interface User {
    id: number;
    name: string;
}

interface AdminUser extends User {
    role: 'admin';
}

// Type — объединение
type Status = 'active' | 'inactive' | 'banned';
type ApiResponse<T> = {
    data: T;
    error?: string;
};

Важно: Никогда не говорите «interface лучше, потому что он быстрее». Разница в производительности микроскопическая. Главное — семантика.

2. Дженерики: как не опозориться на собеседовании

Тема дженериков в TypeScript — любимая мозоль джуниоров. Интервьюеры обожают просить написать функцию, которая принимает массив и возвращает первый элемент с правильным типом.

Пишем дженерик-функцию

function getFirst<T>(arr: T[]): T | undefined {
    return arr[0];
}

const num = getFirst([1, 2, 3]); // number
const str = getFirst(['a', 'b']); // string

Теперь усложним — ограничим дженерик с помощью extends:

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

const user = { name: 'Alice', age: 30 };
getProperty(user, 'name'); // OK: string
getProperty(user, 'email'); // Error: 'email' не входит в keyof

Этот паттерн встречается в каждом втором проекте на React + TypeScript. Обязательно потренируйтесь писать дженерики для TypeScript в своих проектах.

3. Utility Types: ваш секретный арсенал

Знание встроенных утилитарных типов — признак профессионализма. Интервьюер может спросить: «Как сделать все поля необязательными?» или «Как выбрать только часть интерфейса?».

Топ-5 utility types, которые нужно знать

  • Partial<T> — все поля становятся опциональными;
  • Required<T> — все поля обязательны;
  • Pick<T, K> — выбираем только указанные ключи;
  • Omit<T, K> — исключаем указанные ключи;
  • Record<K, V> — создаёт тип объекта с ключами K и значениями V.

Пример, который любят давать на собесе:

interface Todo {
    title: string;
    description: string;
    completed: boolean;
    createdAt: Date;
}

// Обновляем только часть Todo
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
    return { ...todo, ...fieldsToUpdate };
}

// Создаём словарь
const todoMap: Record<string, Todo> = {
    '1': { title: 'Learn TS', description: '', completed: false, createdAt: new Date() }
};

Попробуйте также Readonly, NonNullable и ReturnType — они часто всплывают в вопросах.

4. Type Guards и сужение типов (Narrowing)

Ещё один блок вопросов: «Как проверить, является ли переменная определённым типом?». Здесь в игру вступают Type Guards.

Пишем собственный type guard

interface Fish {
    swim: () => void;
}
interface Bird {
    fly: () => void;
}

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}

function move(pet: Fish | Bird) {
    if (isFish(pet)) {
        pet.swim(); // TS знает, что pet — Fish
    } else {
        pet.fly(); // TS знает, что pet — Bird
    }
}

Обратите внимание на синтаксис pet is Fish. Это и есть type predicate. Без него TypeScript не сможет сузить тип внутри if.

Также изучите typeof, instanceof и in — это базовые guard'ы, которые обязан знать каждый.

5. Mapped Types и Conditional Types

Для senior-позиций вас могут попросить написать свой utility type. Например, сделать все поля массивами.

Mapped Type — делаем все поля опциональными вручную

type MyPartial<T> = {
    [P in keyof T]?: T[P];
};

type PartialUser = MyPartial<User>;
// { id?: number; name?: string }

Conditional Type — выбор типа на основе условия

type IsString<T> = T extends string ? 'yes' : 'no';

type A = IsString<string>; // 'yes'
type B = IsString<number>; // 'no'

Это уже продвинутый уровень. Если вы сможете объяснить, как работает infer в условных типах (например, ReturnType), вас точно запомнят.

6. Работа с async/await и типами ошибок

Собеседование по TypeScript редко обходится без вопроса про типизацию асинхронных операций. Попросят написать функцию, которая возвращает Promise с определённым типом.

async function fetchUser(id: number): Promise<User> {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
        throw new Error('Failed to fetch user');
    }
    return response.json(); // TS выведет Promise<User>
}

Хитрый вопрос: «Как типизировать ошибку в

Блоги

Рекомендаций по книгам