PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    TypeScript дженерики на практике: полный гайд для разработчиков

    TypeScript дженерики на практике: полный гайд для разработчиков

    Аватар автора TypeScript дженерики на практике: полный гайд для разработчиков

    Антон Ларичев

    Иконка календаря30 мая 2026
    typescriptgenericsjavascriptfrontendmiddleИконка уровня middle
    Картинка поста TypeScript дженерики на практике: полный гайд для разработчиков

    Введение

    TypeScript дженерики (generics) — один из самых мощных инструментов системы типов. Они позволяют писать переиспользуемый код, который работает с разными типами данных, сохраняя при этом строгую типизацию. Если функции и классы без дженериков жёстко привязаны к конкретным типам, то обобщённые конструкции принимают тип как параметр и возвращают результат, точно соответствующий входным данным.

    В этом гайде разберём синтаксис, ограничения (constraints), условные типы, утилитные дженерики и практические примеры, которые встречаются в реальной работе с React, Node.js и библиотеками вроде Axios или Prisma.

    Базовый синтаксис дженериков

    Простейший пример — функция, которая возвращает то, что в неё передали. Без дженериков пришлось бы либо использовать any и потерять типизацию, либо писать перегрузки для каждого типа.

    // Функция принимает значение типа T и возвращает то же T
    function identity<T>(value: T): T {
      return value;
    }
    
    // TypeScript сам выведет тип: number
    const num = identity(42);
    
    // Тип можно указать явно
    const str = identity<string>("hello");
    

    Дженерики можно использовать в интерфейсах, типах и классах:

    // Обобщённый интерфейс ответа API
    interface ApiResponse<T> {
      data: T;
      status: number;
      error: string | null;
    }
    
    // Конкретизация под пользователя
    type UserResponse = ApiResponse<{ id: number; name: string }>;
    

    Ограничения через extends

    Иногда нужно гарантировать, что тип-параметр обладает определённой структурой. Для этого применяется ключевое слово extends.

    // T должен иметь поле length
    function logLength<T extends { length: number }>(value: T): T {
      console.log(value.length);
      return value;
    }
    
    logLength("строка"); // ок, у строки есть length
    logLength([1, 2, 3]); // ок, у массива есть length
    // logLength(42); // ошибка: у number нет length
    

    Ещё полезный паттерн — получение типа ключа объекта через keyof:

    // K должен быть одним из ключей объекта T
    function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
      return obj[key];
    }
    
    const user = { id: 1, name: "Anna", role: "admin" };
    const name = getProperty(user, "name"); // тип string
    // getProperty(user, "email"); // ошибка: нет такого ключа
    

    Значения по умолчанию

    Для параметров типа можно задать значение по умолчанию — как для обычных аргументов функций. Это упрощает работу с обобщёнными компонентами.

    // По умолчанию состояние — пустой объект
    interface State<T = Record<string, unknown>> {
      loading: boolean;
      data: T;
    }
    
    // Без явного указания типа
    const initial: State = { loading: false, data: {} };
    

    Условные типы и infer

    Условные типы выглядят как тернарный оператор, но работают на уровне типов. Они особенно полезны в сочетании с infer — для извлечения вложенных типов.

    // Извлекаем тип элемента массива
    type ElementOf<T> = T extends Array<infer U> ? U : never;
    
    type Numbers = ElementOf<number[]>; // number
    type Mixed = ElementOf<(string | boolean)[]>; // string | boolean
    

    Типичный сценарий — получение типа возвращаемого значения функции (это встроенный ReturnType):

    // Реализация ReturnType вручную
    type MyReturnType<T extends (...args: any[]) => any> = 
      T extends (...args: any[]) => infer R ? R : never;
    
    function fetchUser() {
      return { id: 1, name: "Bob" };
    }
    
    type User = MyReturnType<typeof fetchUser>; // { id: number; name: string }
    

    Утилитные дженерики

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

    interface Article {
      id: number;
      title: string;
      body: string;
      publishedAt: Date;
    }
    
    // Все поля становятся необязательными
    type ArticleDraft = Partial<Article>;
    
    // Только нужные поля
    type ArticlePreview = Pick<Article, "id" | "title">;
    
    // Все поля кроме указанных
    type ArticleWithoutDate = Omit<Article, "publishedAt">;
    
    // Делает все поля обязательными
    type StrictArticle = Required<Article>;
    

    Практический пример: типобезопасный fetch

    Соберём небольшую обёртку над fetch, которая возвращает данные нужного типа без приведения через as.

    // Обобщённая функция запроса
    async function apiGet<T>(url: string): Promise<T> {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      return response.json() as Promise<T>;
    }
    
    // Использование с указанием формы ответа
    interface Post {
      id: number;
      title: string;
    }
    
    const posts = await apiGet<Post[]>("/api/posts");
    posts[0].title; // автодополнение и проверка типов
    

    Дженерики в React-компонентах

    Обобщённые компоненты помогают строить переиспользуемые списки, таблицы и селекты без потери типизации элементов.

    // Список с произвольным типом элементов
    interface ListProps<T> {
      items: T[];
      renderItem: (item: T) => React.ReactNode;
    }
    
    function List<T>({ items, renderItem }: ListProps<T>) {
      return <ul>{items.map((item, i) => <li key={i}>{renderItem(item)}</li>)}</ul>;
    }
    
    // item автоматически имеет тип { id: number; name: string }
    <List
      items={[{ id: 1, name: "Anna" }]}
      renderItem={(item) => item.name}
    />;
    

    Частые ошибки

    Чрезмерное обобщение. Не каждой функции нужны дженерики. Если параметр типа используется только один раз и не влияет на возврат — это просто шум. Заменяйте таким случаем обычным типом.

    Использование any вместо ограничений. Конструкция <T extends any> или T = any обнуляет пользу от обобщения. Применяйте unknown, если действительно не знаете тип, или задавайте осмысленные ограничения через extends.

    Игнорирование вывода типов. TypeScript умеет выводить параметры из аргументов. Явное указание identity<string>("x") избыточно, если компилятор сам справляется. Это засоряет код.

    Путаница с keyof и значением ключа. Тип T[K] — это тип значения, а не строки ключа. Помните, что ключ остаётся литералом, а через индексный доступ вы получаете именно поле.

    Дженерик вместо union. Если функция принимает строго два варианта типа, перегрузки или union читаются понятнее, чем обобщение.

    Заключение

    Дженерики превращают TypeScript из строгого, но негибкого языка в выразительный инструмент моделирования данных. Они позволяют описать связь между входом и выходом функции, между состоянием и его трансформациями, между ключом объекта и типом значения. Начните с простых случаев — обёрток над API, утилит для коллекций, компонентов-списков — и постепенно подключайте условные типы и infer, когда библиотечный код требует точного описания форм данных. Главное правило: дженерик должен делать код безопаснее и читаемее, а не наоборот.

    Иконка глаза1 007

    Комментарии

    0

    Постройте личный план изучения Angular до уровня Middle — бесплатно!

    Angular — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Лучшие курсы по теме

    изображение курса

    Основы разработки

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    бесплатно
    Подробнее
    изображение курса

    Основы Git

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    HTML и CSS

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Регулярные выражения в JavaScript: полное руководство
    Иконка аватараАнтон
    Иконка календаря06 августа 2026
    JavaScriptрегулярные выраженияregexp+ 2middleИконка уровня middle

    Регулярные выражения в JavaScript: полное руководство

    Регулярные выражения в JavaScript позволяют искать, проверять и заменять текст по шаблону. Разбираем синтаксис, методы и частые ошибки с примерами.

    Иконка чипа0
    Иконка глаза519
    Иконка комментариев0
    Картинка поста CSS Grid: полное руководство по сеткам в 2024
    Иконка аватараАнтон
    Иконка календаря18 июля 2026
    csscss-gridвёрстка+ 2middleИконка уровня middle

    CSS Grid: полное руководство по сеткам в 2024

    CSS Grid — мощная система сеток для создания двумерных макетов. Разбираем все свойства, паттерны и типичные ошибки на практических примерах.

    Иконка чипа+1
    Иконка глаза552
    Иконка комментариев0
    Картинка поста GraphQL vs REST: что выбрать для API в 2026 году
    Иконка аватараАнтон
    Иконка календаря11 июля 2026
    graphqlrestapi+ 3middleИконка уровня middle

    GraphQL vs REST: что выбрать для API в 2026 году

    GraphQL vs REST — разбираем ключевые отличия, сценарии применения и подводные камни каждого подхода, чтобы выбрать правильный инструмент для вашего проекта.

    Иконка чипа0
    Иконка глаза911
    Иконка комментариев0
    Иконка чипа0