Generics
Тема дорожной карты · Frontend разработчик
TypeScript generics — это механизм написания переиспользуемых типобезопасных функций, классов и интерфейсов, работающих с различными типами и сохраняющих информацию о типе в месте вызова. Обобщение объявляется с помощью параметра типа в угловых скобках — function identity<T>(value: T): T { return value; } — и TypeScript выводит аргумент типа в месте вызова, или его можно указать явно. Generics пронизывают всю экосистему React и TypeScript: useState<User | null>(null) ограничивает тип состояния, useRef<HTMLInputElement>(null) типизирует DOM-ссылки, а useQuery<Data, Error> из TanStack Query обеспечивает сквозную типобезопасность от запроса до рендеринга. Ограничения (<T extends object>) и параметры типа по умолчанию (<T = string>) уточняют допустимые обобщённые типы, тогда как условные типы (T extends U ? X : Y) и отображаемые типы ({ [K in keyof T]: ... }) открывают продвинутые паттерны generics, применяемые в утилитарных типах и библиотечных API.
Как это работает
Generics добавляет статическую типизацию поверх JavaScript через компилятор tsc или трансформер (esbuild, swc). Type-аннотации в .ts / .tsx; вывод — обычный JS. tsconfig.json контролирует строгость — strict: true современный дефолт, включает null-checks, no-implicit-any, no-implicit-this и больше. Generics делают функции и компоненты переиспользуемыми между типами. Utility-типы (Partial, Pick, Omit, Required, Readonly, Record) выводят типы из существующих.
Когда применять
TypeScript — в каждый новый frontend-проект: безопасный рефакторинг + IDE-интеллект + ловля багов на сборке окупают трение за первую неделю. Мигрируйте JS-кодовую базу инкрементально через allowJs: true. unknown лучше any для неизвестных форм; намеренные касты (as Type) — только на границах. Доверяйте inference для локалов; аннотируйте сигнатуры функций + API модулей.
Типичные ошибки
Ловушки Generics: any повсюду, когда типы мешают (теряете смысл — рефакторьте или unknown); as Type-касты, лгущие компилятору; over-engineered generic constraints в библиотечном коде; не включили strictNullChecks (тихие undefined-баги возвращаются); расходящиеся runtime + type-check пайплайны (esbuild компилирует, tsc проверяет — оба должны быть в CI).