Сталкивался ли с дженериками в TypeScript?

«Сталкивался ли с дженериками в TypeScript?» — вопрос из категории TypeScript, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, активно использую дженерики (Generics) в TypeScript для Node.js-проектов. Они необходимы для создания переиспользуемых, типобезопасных компонентов, когда точный тип известен только в момент использования.

Практические примеры из моего опыта:

  1. Универсальные функции-хелперы:

    // Функция для оборачивания ответа API в стандартный формат
    interface ApiResponse<T> {
      success: boolean;
      data: T;
      error?: string;
    }
    
    function createResponse<T>(data: T, error?: string): ApiResponse<T> {
      return {
        success: !error,
        data,
        ...(error && { error })
      };
    }
    
    // Использование с разными типами данных
    const userResponse = createResponse<User>({ id: 1, name: 'John' });
    const listResponse = createResponse<string[]>(['item1', 'item2']);
  2. Типизация репозиториев для работы с БД (паттерн Repository):

    interface IRepository<T> {
      findById(id: number): Promise<T | null>;
      create(entity: Partial<T>): Promise<T>;
      update(id: number, updates: Partial<T>): Promise<T | null>;
    }
    
    class UserRepository implements IRepository<User> {
      async findById(id: number): Promise<User | null> {
        // ... логика поиска пользователя в БД
      }
      // ... реализация других методов
    }
  3. Работа с промисами и асинхронными операциями:

    async function fetchData<T>(url: string): Promise<T> {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Ошибка сети');
      return response.json() as Promise<T>; // Указываем ожидаемый тип данных
    }
    
    // Вызов с конкретным типом
    interface Product { id: number; title: string; }
    const product = await fetchData<Product>('/api/products/1');

Дженерики делают код более предсказуемым и защищают от ошибок типов на этапе компиляции.