johnymkp
@johnymkp

Как правильно сформировать объект-результат в перегруженной функции в TypeScript?

Разбираю раздел про перегрузку функций в ТС. Вроде суть понял, что на все перегрузки должна быть одна комбинированная реализация, которая учитывает все особенности вызова. Однако не понимаю, как правильно собрать итоговый объект. Вот сделал пример. Работает, но смущает вот что:
1. Я использовал any для объекта, а значит в него кроме нужных свойств можно накидать произвольных.
2. Если переписать как-то так
Рефакторинг
function reserve(from: Date, toOrDest: Date | string, destination?: string): Ticket {
  if (toOrDest instanceof Date && destination !== undefined) {
    return { 
      type: "two-way",
      from,
      to: toOrDest,
      destination
    }
  } else if (typeof toOrDest === 'string') {
    return { 
      type: "one-way",
      from,
      destination: toOrDest
    }
  } 
  throw new Error("Некорректный вызов функции резервирования билета");
}

тогда, во-первых, появляется дублирование кода (свойство from приходится писать в обоих ветках отдельно, хотя оно во всех случаях гарантированно присутствует), а, во-вторых, приходится писать выброс ошибки, что выглядит некрасиво и к тому же в принципе как будто не может случиться, т.е. получается строчка чисто чтобы компилятор не ругался.

Покажите, как сделать канонично с точки зрения программирования на TS?
  • Вопрос задан
  • 85 просмотров
Решения вопроса 1
Alexandroppolus
@Alexandroppolus
кодир
type Reserve = {
  (from: Date, to: Date, destination: string): Ticket;
  (from: Date, destination: string): Ticket
};
  
const reserve: Reserve = (from: Date, ...args: [toOrDest: Date, destination: string] | [destination: string]): Ticket => {
  const isOne = args.length === 1;

  return {
    type: isOne ? "one-way" : "two-way",
    from,
    destination: isOne ? args[0] : args[1],
    ...(isOne ? {} : {to: args[0]})
  };
};


На самом деле, такая запись уже даёт перегрузку функции, даже если отсюда вообще выкинуть тип Reserve. Но тогда при наведении мыши на reserve будет не совсем понятная подсказка (хотя автокомплит вполне корректный).

Ну а для данного примера лучше всего просто передвинуть параметр destination на нулевую позицию, тогда у тебя будет просто необязательный параметр в конце списка
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы