Сигнатура функции - это по сути ее тип, который состоит из списка аргументов с типами и типа возвращаемого значения.
Имплементация функции - это функция с телом.
То есть следующие строки - это сигнатуры:
function position(): MyPosition
function position(a:number, b:number): MyPosition
function position(a:number): MyPositionWithDefault
Это тоже сигнатура:
function position(a?: number, b?:number)
, но она так же является частью имплементации:
function position(a?: number, b?:number) {
if (!a && !b) {
return {x: undefined, b: undefined}
}
if(a && !b) {
return {x: a, b: undefined, default: a.toString()}
}
return {x: a, y: b}
}
Перегрузки в TS работают по особенному, не так как в других языках. Все дело в том, что на выходе должен получится JS, в котором никаких перегрузок нет. Поэтому перегрузки работают только на уровне типов.
Поэтому Вы сначала перечисляете список сигнатур, которые станут типом функции для вызывающей стороны, а потом пишите имплементацию, у которой сигнатура должна быть обобщением всех перегрузок, так как именно она используется для проверки типов внутри функции.
Еще один важный момент для данного примера - это вывод типов. Если где-то тип не указать, то TS попробует его вывести, но делает он это весьма топорно - из первого значения которое будет присвоено переменной, ну и из первого return если речь идет о выводе возвращаемого значения функции.
В Вашем случае TS выведет возвращаемое значение имплементации из следующей строчки:
return {x: undefined, b: undefined}
Тип такого значения будет:
interface ReturnTypeOfPosition {
x: undefined
b: undefined
}
Проблема тут в двух вещах, во-первых в поле
b вместо поля
y, во-вторых в отсутствии поля
default.
Если исправить так:
function position(): MyPosition
function position(a: number, b: number): MyPosition
function position(a: number): MyPositionWithDefault
function position(a?: number, b?: number): MyPosition | MyPositionWithDefault {
if (!a && !b) {
return {x: undefined, y: undefined}
}
if(a && !b) {
return {x: a, y: undefined, default: a.toString()}
}
return {x: a, y: b}
}
то все будет ок
Ну и еще важный момент про перегрузки, TS использует в месте вызова ту перегрузку, которая первой подошла по аргументам, пробуя их в том порядке, как они записаны у Вас в коде, сверху вниз. Соответственно остальные типы в месте вызова будут выводится из данного факта.
P.S. у меня в профиле есть ссылка на доклад по системе типов TS, про перегрузки там тоже есть. Система типов в TS полностью построена на математике множеств, если понять эту математику, то поймете и TS.