Типовые параметры ("дженерики") функций могут быть выведены из переданных аргументов, что здесь и происходит. ТС сопоставляет тип аргумента функции с типом аргумента в выражении её вызова и пытается вывести тип для <T>
. В хендбуке есть соответствующий раздел для ознакомления. К сожалению, у TS отсутствует официальная спецификация и нормальная документация, поэтому изучить механизм вывода типов более детально можно только в пул реквестах, ишью и исходниках на гитхабе.
"Более правильного" способа написать эту функцию не существует, без <T>
здесь не обойтись. Вас не должно смущать что он явно не указывается при вызове. Типовой параметр позволяет подставлять типы при вызове, а не при определении, что даёт возможность выстраивать зависимости между типами в сигнатуре функции. Соответственно, если такие зависимости вам нужны, вы должны написать дженерик.
В вашем случае возвращаемый тип функции зависит от типа её аргумента.
Пример:
declare function f(arg: unknown): typeof arg
declare function g<T>(arg: T): typeof arg
const a = f(1)
const b = g(1)
Поскольку тип аргумента функции f
задан при определении, typeof arg
всегда будет unknown
. Но для функции g
он будет вычисляться каждый раз при вызове, и typeof arg
будет возвращать выведенный тип. Дженерик здесь убрать нельзя.
Если же заменить тип возвращаемого значения в этих функция, например, на void
, то зависимостей от типа аргумента не останется. В таком случае нам не будет важно в какой именно момент определился тип аргумента, поэтому дженерик будет излишним.
declare function f(arg: unknown): void
declare function g<T>(arg: T): void
f(1)
g(1)