ПрограммированиеFullstack разработчик

Опишите механизм автоматически получаемых типов (ReturnType, Parameters) в TypeScript. Для чего их используют, каковы нюансы работы при типизации сложных функций (например, с перегрузкой)?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

ReturnType<T> и Parameters<T> — это utility types TypeScript, которые позволяют автоматически вывести тип возвращаемого значения функции (ReturnType) или массив типов её параметров (Parameters).

Это особенно удобно для обеспечения согласованности типов между разными частями приложения и для реализации generic-обёрток.

Пример использования:

function fn(a: number, b: string): boolean { return b.length > a; } type FnReturn = ReturnType<typeof fn>; // boolean type FnParams = Parameters<typeof fn>; // [number, string]

Нюансы с перегрузкой функций: При перегрузке функций ReturnType определяет последний вариант сигнатуры, а Parameters — все возможные перегрузки:

function overloaded(x: number): number; function overloaded(x: string): string; function overloaded(x: any): any { return x; } type OverRet = ReturnType<typeof overloaded>; // any type OverParams = Parameters<typeof overloaded>; // [any]

То есть, типизация utility типов не всегда "видит" все перегрузки, поэтому статичная типизация становится менее предсказуемой.

Вопрос с подвохом.

Можно ли с помощью ReturnType и Parameters получить типы всех возможных перегрузок кастомной функции, определяя каждую перегрузку по отдельности?

Ответ:

Нет. Utility типы ReturnType и Parameters анализируют только "объединённую" сигнатуру функции — как она описана для реализации. Они не позволяют получить типы каждой индивидуальной перегрузки — только итоговой реализованной сигнатуры.

Пример:

type P = Parameters<typeof overloaded>; // [any], а не [number], [string]

Примеры реальных ошибок из-за незнания тонкостей темы


История

Разработчики написали обёртку aroundMethod, используя ReturnType<T> для типизации возвращаемого значения. При этом функция-обёртка применялась к перегруженной функции. Итог: typy были слишком общими (any), и при ошибках компилятор не сигнализировал несоответствие возвращаемых значений. Поздно обнаружили баг при работе с boolean'ами вместо string.


История

В попытке вывести параметры для множества API-функций через Parameters<T>, разработчик не учёл перегрузки методов. Возникла проблема с "ошибочными" типами, где вместо [string, number] ожидалось [any]. Unit-тесты не ловили эту ошибку из-за монтажа через реализацию, а реальные пользователи API получили баги на проде.


История

Мигрируя большой код с JavaScript на TypeScript, разработчики всё типизировали через ReturnType. Позже поняли, что реализация сильно отличается от декларации перегрузок. Из-за этого сценарии с ошибочными аргументами вызывали неожиданные runtime-исключения (например, TypeError: x is undefined).