Как пройти собеседование по TypeScript: топ вопросов с примерами
TypeScript прочно занял нишу стандарта для enterprise-разработки на JavaScript. Если вы готовитесь к собеседованию, важно не просто знать синтаксис, но и понимать, как работают типы, дженерики и утилиты. В этой статье мы разобрали топ вопросов, которые часто задают на технических интервью, с подробными ответами и примерами кода.
Материал будет полезен как junior-разработчикам, так и тем, кто хочет освежить знания перед важной встречей.
1. Что такое TypeScript и зачем он нужен?
TypeScript — это строго типизированное надмножество JavaScript, которое компилируется в обычный JS. Основная цель — добавить статическую типизацию, что позволяет:
- Ловить ошибки на этапе компиляции, а не в runtime.
- Улучшить читаемость и поддерживаемость кода.
- Получить автодополнение и рефакторинг в IDE.
Пример:
// JavaScript
function add(a, b) {
return a + b; // a и b могут быть чем угодно
}
// TypeScript
function add(a: number, b: number): number {
return a + b; // ошибка компиляции, если передать строку
}
На собеседовании важно подчеркнуть, что TypeScript не заменяет JavaScript, а дополняет его, делая код безопаснее.
2. Базовые типы и их использование
TypeScript предлагает широкий набор базовых типов. Вопросы на эту тему проверяют ваше понимание системы типов.
Перечислите основные типы:
number,string,booleannull,undefinedany— отключает проверку типов (старайтесь избегать)void— для функций, которые ничего не возвращаютnever— для функций, которые никогда не завершаются (например, выбрасывают исключение)
Пример с union-типами:
type Status = 'active' | 'inactive' | 'pending';
let userStatus: Status = 'active'; // только одно из трёх значений
Часто спрашивают про разницу между interface и type. Ответ: interface можно расширять (extends), а type — нет. Для объектов предпочтительнее interface, для примитивов и union — type.
3. Дженерики (Generics) — основа гибкости
Дженерики позволяют создавать компоненты, работающие с разными типами без потери типизации. Это один из самых частых вопросов.
Пример простого дженерика:
function identity<T>(arg: T): T {
return arg;
}
const result = identity<string>('hello'); // тип string
const numberResult = identity(42); // тип number (вывод типа)
Вопрос: Как ограничить дженерик?
Используйте ключевое слово extends:
function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
}
getLength('hello'); // 5
getLength([1,2,3]); // 3
// getLength(123); // ошибка: у number нет length
Также спросят про дженерики в интерфейсах:
interface ApiResponse<T> {
data: T;
status: number;
error?: string;
}
const userResponse: ApiResponse<{ id: number; name: string }> = {
data: { id: 1, name: 'Alice' },
status: 200
};
4. Утилитарные типы (Utility Types)
Встроенные утилиты TypeScript упрощают манипуляции с типами. Знание их — признак опытного разработчика.
Топ-5 утилит, которые стоит знать:
Partial<T>— делает все поля необязательными.Required<T>— делает все поля обязательными.Pick<T, K>— выбирает только указанные ключи.Omit<T, K>— исключает указанные ключи.Record<K, V>— создаёт тип с ключами K и значениями V.
Пример использования:
interface User {
id: number;
name: string;
email: string;
age: number;
}
// Только имя и email
type UserContact = Pick<User, 'name' | 'email'>;
// Все поля, кроме возраста
type UserWithoutAge = Omit<User, 'age'>;
// Объект с ключами-строками и значениями-числами
type Dictionary = Record<string, number>;
const scores: Dictionary = { math: 95, english: 88 };
На собеседовании могут попросить реализовать свой Partial:
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
5. Type Guards и приведение типов
Type Guards — это механизмы, которые помогают TypeScript сузить тип в условных блоках. Это важная тема для работы с union-типами.
Пример с typeof:
function formatValue(value: string | number): string {
if (typeof value === 'string') {
return value.toUpperCase(); // TS знает, что это string
}
return value.toFixed(2); // TS знает, что это number
}
Пример с пользовательским guard:
interface Cat {
meow(): void;
}
interface Dog {
bark(): void;
}
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeSound(animal: Cat | Dog) {
if (isCat(animal)) {
animal.meow(); // безопасно
} else {
animal.bark();
}
}
Также спросят про as (приведение типов) — используйте его осторожно, только когда уверены в типе.
6. Модификаторы доступа в классах
TypeScript поддерживает три модификатора: <