Каков наилучший способ объявить функцию TypeScript с дискриминированным объединением, которое возвращает тот же тип, что и ее параметр? - PullRequest
1 голос
/ 04 марта 2020

Учитывая эту упрощенную ванильную JS функцию:

function getStringOrNumber(val) {
  if (typeof val === 'string') {
      return 'It was a string';
  } else {
      return 5;
  }
}

Как я могу сказать TypeScript, что когда он получает строку, он возвращает строку, а когда он получает число, он возвращает число?

Я экспериментировал с различными методами и обнаружил, что использование этих перегрузок работает, но это кажется слишком сложным, и мне интересно, есть ли что-то, что я пропускаю. В частности, в этом решении я не понимаю, зачем нужна третья строка (см. Ссылку ниже для получения дополнительной информации).

function useOverloadsExtra(val: string): string
function useOverloadsExtra(val: number): number
function useOverloadsExtra(val: string | number): string | number
function useOverloadsExtra(val: string | number): string | number {
    if (typeof val === 'string') {
        return 'It was a string';
    } else {
        return 5;
    }
}

Вот другие решения, которые я пробовал

1 Ответ

0 голосов
/ 04 марта 2020

Ваше решение по перегрузкам близко. Проблема в вашем тесте. В вашем тесте вы вызываете метод, передающий объединение в качестве параметра, но объединение не является допустимым значением: только string и number. Последняя перегрузка («перегрузка реализации») не является частью подписи . Таким образом, ваш тест должен выполнить сужение, например:

function getValOverloads(val: string | number): string | number {
    if (typeof val === 'string')
        return useOverloads(val);
    else
        return useOverloads(val);
}

Если вы хотите иметь возможность передать объединение (и, таким образом, получить объединение в качестве возвращаемого значения), вы должны добавить третью перегрузку (просто как вы сделали на useOverloadsExtra).

...