Введение
Я уже более 7 лет активно использую TypeScript, применяя его в самых разных сценариях — от простых типизированных переменных до сложных условных типов и интерполяции. Однако TypeScript продолжает удивлять: сегодня я открыл для себя ещё один элегантный сценарий использования автовыведения типов в дженериках и функциях.
В этой статье разберём, как TypeScript автоматически выводит типы в дженериках на примере функции fetchFile
из моего кода.
1. Что такое автовыведение типов?
Автовыведение типов (Type Inference) — это способность TypeScript автоматически определять типы данных без их явного указания.
Базовые примеры:
let age = 25; // Вывод: `number`
const name = "Alice"; // Вывод: `string`
TypeScript понимает, что age
— это number
, а name
— string
.
Но что, если мы работаем с дженериками и функциями?
2. Автовыведение в дженериках и функциях
Рассмотрим мой пример с функцией fetchFile
:
type FileContentFetcher<TParams> = (params: TParams) => CancelablePromise<TParams>;
export const fetchFile = <TParams>(getFileContent: FileContentFetcher<TParams>) => {
return (requestParams: TParams) => {
getFileContent(requestParams).then(downloadFile);
};
};
Здесь TypeScript делает три ключевых вывода:
1. Автовыведение TParams на основе переданной функции
Когда мы вызываем:
fetchFile(API.findExcel)({ ... });
TypeScript:
Смотрит на тип
findExcel
.Определяет, что его параметр имеет структуру:
{ requestBody: { docPkgVerEndDtFrom: string; docPkgVerEndDtTo: string } }
Автоматически подставляет этот тип в
TParams
.
2. Проверка соответствия аргументов
Если передать неверные параметры:
fetchFile(API.Search.SearchApiService.findDocumentPackagesExcel1)({
requestBody: {
invalidField: "2025-05-05", // 🚫 Ошибка!
},
});
TypeScript сразу укажет на ошибку, потому что invalidField
не соответствует ожидаемому TParams
.
3. Автовыведение возвращаемого типа
Функция fetchFile
возвращает новую функцию, которая принимает TParams
. TypeScript сохраняет связь типов на всех уровнях вложенности.
3. Почему это мощно?
Минимум boilerplate-кода
Не нужно явно указыватьTParams
— TypeScript выводит его автоматически.Безопасность типов
Если API изменится (например, полеdocPkgVerEndDtFrom
переименуют), TypeScript сразу покажет ошибку в местах вызова.Гибкость
Одна и та же функцияfetchFile
работает с любым API-методом, возвращающимBlob
.
4. Где ещё полезно автовыведение в дженериках?
a) Утилиты для API
const createApiCall = <TResponse, TParams>(fetcher: (params: TParams) => TResponse) => {
return (params: TParams) => fetcher(params);
};
const getUser = createApiCall(API.getUser); // TParams выводится из API.getUser
b) Обёртки для React-хуков
const useFetch = <TData>(url: string) => {
const [data, setData] = useState<TData | null>(null);
// ...
};
const { data } = useFetch("/api/users"); // TData выводится из возвращаемого значения API
5. Ограничения автовыведения
Сложные дженерики
Если тип слишком сложный, TypeScript может не вывести его автоматически — тогда нужно указывать явно:fetchFile<MyCustomParams>(someFetcher);
Перегрузка функций
Для перегруженных функций иногда нужно явно прописывать типы.
Вывод
Автовыведение типов в TypeScript — это мощный инструмент, который особенно полезен в дженериках и функциях. Мой пример с fetchFile
показывает, как TypeScript автоматически связывает типы между переданной функцией и её аргументами, обеспечивая безопасность и удобство разработки.
Совет:
Используйте автовыведение везде, где можно.
Явно указывайте типы только в сложных случаях.
Теперь, когда вы знаете этот паттерн, попробуйте применить его в своих проектах! 🚀