Как работает перегрузка функций в TypeScript
Что проверяют
Понимаете ли вы, что перегрузка в TypeScript существует только на уровне типов: в JavaScript остаётся одна функция, и ветвление по аргументам вы пишете сами. Следом обычно спрашивают, когда перегрузка лучше объединения типов или дженерика.
Как отвечать
Перегрузка это несколько сигнатур без тела и одна реализация под ними:
- сигнатуры перегрузок: снаружи видны только они. Сигнатура реализации скрыта, вызвать функцию по ней нельзя;
- совместимость: реализация обязана принимать всё, что описано в перегрузках, поэтому её параметры обычно объединения или
unknown, а внутри стоят проверкиtypeof,Array.isArray,in; - порядок разрешения: компилятор перебирает сигнатуры сверху вниз и берёт первую подходящую, поэтому специфичные ставят выше общих;
- где это оправдано: тип результата зависит от типа аргумента, например
parse(s: string): Dateиparse(s: string[]): Date[], или у функции принципиально разные наборы параметров. Так описаныcreateElementиaddEventListenerвlib.dom.d.ts; - методы и стрелки: в классах и интерфейсах перегрузки пишутся так же. У стрелочной функции объявить их нельзя, нужен тип с несколькими сигнатурами вызова:
{ (s: string): Date; (s: string[]): Date[] }.
Правило из документации TypeScript: если хватает объединения или необязательного параметра, выбирайте их. Пара greet(name) и greet(name, age) решается одной сигнатурой с age?: number, перегрузка тут лишняя.
Где спотыкаются
Не знают, что аргумент типа string | string[] не пройдёт ни через одну из двух перегрузок: TypeScript их не объединяет. Приходится добавлять третью сигнатуру с объединением, и тогда стоит спросить себя, нужны ли первые две.
Верят, что компилятор проверяет реализацию против каждой перегрузки. Проверка мягкая: реализация может вернуть Date там, где перегрузка обещает Date[], и ошибки не будет. Соответствие веток и типов результата остаётся на вашей совести.
Применяют ReturnType или Parameters к перегруженной функции и удивляются результату: эти утилиты берут только последнюю сигнатуру.