История вопроса:
TypeScript поддерживает перегрузку методов, аналогично другим строго типизированным языкам (например, Java или C#), однако синтаксис перегрузки в TypeScript концептуально отличается. Здесь допускается несколько сигнатур, но только одна реализация. Это может привести к путанице для разработчиков, знакомых с классической перегрузкой.
Проблема:
Распространённая ошибка — попытаться определить несколько методов с разными наборами параметров. В результате возникает ошибка компиляции, так как TypeScript требует одну реализацию, реализующую все варианты сигнатур.
Решение:
Перегрузка достигается объявлением нескольких сигнатур метода, а затем реализации, соответствующей всем вариантам. Для корректного различения параметров обычно применяются type guards или instanceof.
Пример кода:
class MyLogger { log(message: string): void; log(message: string, level: 'info' | 'error'): void; log(message: string, level?: 'info' | 'error'): void { const lvl = level ?? 'info'; console.log(`[${lvl}] ${message}`); } }
Ключевые особенности:
Можно ли реализовать две реализации одного метода с разными наборами параметров?
Нет. В TypeScript только одна реализация разрешена. Несколько методов с одинаковым именем — синтаксическая ошибка.
Как типизировать rest-параметры при перегрузке методов, чтобы не потерять строгую типизацию?
Рекомендуется в сигнатурах описывать точные параметры, а в реализации — максимально обобщённые:
class Test { doWork(a: number): void; doWork(a: string): void; doWork(a: number | string): void { //... } }
Что произойдет, если возвращаемый тип перегруженных сигнатур разный?
TypeScript потребует, чтобы реализация возвращала объединённый тип (Union). В противном случае — ошибка компиляции.
class X { get(value: number): string; get(value: string): number; get(value: number | string): string | number { return typeof value === 'number' ? 'number' : 42; } }
В продукте пытались реализовать два метода с одинаковым именем для разных типов параметров в классе. После компиляции метод "замещался" последним объявлением, все остальные версии игнорировались, и появлялись баги.
Плюсы:
Минусы:
Сделали несколько сигнатур с union-type параметрами, а в методе обработали все варианты через type guards. Компилятор сразу предупредил о типовых проблемах.
Плюсы:
Минусы: