Этот вопрос проверяет понимание обобщенного программирования в TypeScript и практическое применение дженериков для создания переиспользуемых типовозопасных конструкций.
Дженерики (обобщения) применяются для создания переиспользуемых компонентов, которые работают с разными типами данных, сохраняя типобезопасность. Они позволяют параметризовать типы, чтобы один и тот же код мог работать с различными типами без потери информации о типах на этапе компиляции.
Дженерики предоставляют способ создания компонентов, которые могут работать с различными типами, а не с одним конкретным.
Без дженериков мы вынуждены использовать any, что приводит к потере типобезопасности:
typescript
// Проблема: теряется информация о типе
function identity(value: any): any {
return value;
}
const result = identity(42); // Тип result - any, а не numbertypescript
// Решение: тип сохраняется
function identity<T>(value: T): T {
return value;
}
const num = identity(42); // Тип: number
const str = identity("hello"); // Тип: string
const bool = identity(true); // Тип: booleantypescript
function getFirst<T>(array: T[]): T | undefined {
return array[0];
}
const numbers = getFirst([1, 2, 3]); // Тип: number | undefined
const strings = getFirst(["a", "b", "c"]); // Тип: string | undefinedtypescript
interface Response<T> {
data: T;
status: number;
message: string;
}
const userResponse: Response<User> = {
data: { id: 1, name: "Иван" },
status: 200,
message: "OK"
};
const productResponse: Response<Product> = {
data: { id: 1, title: "Телефон", price: 1000 },
status: 200,
message: "OK"
};typescript
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
const num = numberStack.pop(); // Тип: number | undefined
const stringStack = new Stack<string>();
stringStack.push("hello");Можно ограничивать типы, с которыми могут работать дженерики:
typescript
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}
logLength("строка"); // OK - у строки есть length
logLength([1, 2, 3]); // OK - у массива есть length
// logLength(42); // Ошибка - у числа нет lengthtypescript
interface Pagination<T = any> {
data: T[];
page: number;
total: number;
}
// Можно явно указать тип или использовать any по умолчанию
const usersPagination: Pagination<User> = { /* ... */ };
const defaultPagination: Pagination = { /* ... */ }; // T = anytypescript
function pair<K, V>(key: K, value: V): [K, V] {
return [key, value];
}
const stringNumber = pair("age", 30); // Тип: [string, number]
const numberBoolean = pair(1, true); // Тип: [number, boolean]Вывод: Дженерики необходимы для создания переиспользуемого типобезопасного кода. Они позволяют писать гибкие компоненты, которые сохраняют информацию о типах и обеспечивают проверку на этапе компиляции.
Frontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию