> Что такое дженерики в TypeScript и для чего они используются (TypeScript)
Уровень: junior · Роль: frontend · Категория: Технические вопросы
Компании: Иннотех, Альфа-банк, Soft_Media_Group, ООО Премиум ИТ Солюшен, Kodix, IT-One, GetMatch, Арго, TYMY, LoyaltyLabs, SmartWay
Стек: TypeScript
> Пример ответа
Короткий ответ
Дженерики (generics) в TypeScript - это механизм, позволяющий создавать компоненты (функции, классы, интерфейсы), которые работают с разными типами данных, сохраняя при этом строгую типизацию. Они используются для повышения переиспользуемости кода и type safety без потери информации о конкретном типе. Например, функция identity<T>(arg: T): T возвращает значение того же типа, который был передан.
Подробное объяснение
Дженерики решают проблему, когда нужно написать функцию или класс, работающий с разными типами, но без использования any (который отключает проверку типов). Вместо того чтобы дублировать код для каждого типа (например, number, string, object), мы используем параметр типа - обычно обозначается как T, U, K и т.д.
Основные сценарии использования:
- Типизированные коллекции:
Array<T>- массив элементов типаT. - Функции с сохранением типа: функция, принимающая и возвращающая значение одного типа.
- Constraints (ограничения): с помощью
extendsможно ограничить допустимые типы, например,T extends HasLength. - Generic constraints with keyof: доступ к свойствам объекта по ключу с проверкой типа.
- Generic classes: классы, где тип полей или методов определяется при создании экземпляра.
Дженерики компилируются в обычный JavaScript без потери информации о типах - проверки происходят только на этапе компиляции.
На практике
В реальных проектах дженерики используются повсеместно:
- React: типизация пропсов компонентов через
React.FC<Props>илиuseState<T>(). - API-клиенты: функция
fetchData<T>(url): Promise<T>для типизации ответов. - Redux Toolkit:
createSliceс generic для state и actions. - Utility types:
Partial<T>,Pick<T, K>,Record<K, V>- все они дженерики. - Хранилища (store): generic-классы для работы с разными сущностями.
Пример из реального кода: функция для обновления состояния в Redux reducer:
TYPESCRIPTfunction updateField<T extends Record<string, any>, K extends keyof T>(obj: T,key: K,value: T[K]): T {return { ...obj, [key]: value };}
Пример кода
TYPESCRIPT// Базовая generic-функцияfunction firstElement<T>(arr: T[]): T | undefined {return arr[0];}const num = firstElement([1, 2, 3]); // numberconst str = firstElement(['a', 'b']); // string// Generic-интерфейсinterface ApiResponse<T> {data: T;status: number;error?: string;}// Generic-классclass Stack<T> {private items: T[] = [];push(item: T): void {this.items.push(item);}pop(): T | undefined {return this.items.pop();}}// Constraintsfunction getLength<T extends { length: number }>(arg: T): number {return arg.length;}getLength('hello'); // 5getLength([1, 2, 3]); // 3// getLength(123); // Ошибка: number не имеет length
Как отвечать на собеседовании
Начни с простого определения: "дженерики - это параметризованные типы, позволяющие писать код, который работает с разными типами, но сохраняет типовую безопасность". Приведи пример из стандартной библиотеки TypeScript - Array<T>. Затем объясни, чем это лучше any: дженерики не теряют информацию о типе, а any её отключает.
Если спросят про ограничения, упомяни extends и keyof. Хорошо показать понимание, что дженерики существуют только на этапе компиляции и не влияют на рантайм.
Что проверяет интервьюер
- Понимание базовой концепции параметризации типов.
- Умение отличать дженерики от
anyи от union-типов. - Знание синтаксиса:
function<T>,interface<T>,class<T>. - Понимание constraints и их практического применения.
- Способность объяснить, зачем это нужно в реальном проекте.
Типичные ошибки
- Путать дженерики с
any: "дженерики - это то же самое, что any, только с другим синтаксисом". Это неверно -anyотключает проверку типов, дженерики её сохраняют. - Неправильно расставлять скобки:
function<T>вместоfunction <T>(пробел необязателен, но важно соблюдать синтаксис). - Забывать про множественные параметры:
function pair<T, U>(a: T, b: U): [T, U]. - Использовать дженерики там, где достаточно конкретного типа или union-типа (overengineering).
- Не понимать разницы между
T extends SomeTypeиT = SomeType(constraint vs default type).
> Похожие задачи по frontend
Используешь ли условные типы (conditional types) в TypeScript
Что происходит при объединении полей с конкретными значениями в TypeScript?
В чем разница между типами void и never в TypeScript
В чем отличие Type и Enum в TypeScript и как они выглядят после компиляции
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью