Generics (обобщённые типы) позволяют писать универсальный код, который работает с разными типами, сохраняя строгую типовую безопасность.
Синтаксис использования:
function identity<T>(value: T): T { return value; } const x = identity<string>('test'); // T = string
Где применяют:
Пример с ограничением типа:
function getFirst<T extends { length: number }>(arr: T): T { return arr[0]; }
Вопрос: Обязательно ли указывать конкретный тип при вызове функции с Generic параметром?
Ответ:
Не обязательно. TypeScript сам выводит (инференсит) типы по переданным значениям, если возможно. Но иногда явно указывать удобно, например, если из значений тип не ясен или есть несколько вариантов.
function identity<T>(value: T): T { return value; } identity(5); // T = number (auto) identity<string>('s'); // T = string (явно)
История
В e-commerce проекте написали generic-репозиторий для разных сущностей, но забыли про ограничение типа. В результате в generic мог попасть любой объект, и один раз сохранили сущность с несовместимыми полями. Типы не защитили от ошибки.
История
Шаблонную функцию передали массив, ожидали получить массив с типом элементов. Но функция возвращала any[], так как generic не был явно указан и TypeScript не смог вывести тип. Ошибку заметили только на проде.
История
Начинающий разработчик создал generic-класс без ограничения типа, использовал поле, которого не было во всех типах. Компилятор не ругался, но при доступе к несуществующему свойству весь функционал ломался.