Почему Typescript не может определить правильный тип на основе оператора переключения перечисления? - PullRequest
0 голосов
/ 08 июля 2020
enum Test {
  one,
  two,
}

const play = (n: Test) => {
  switch (n) {
    case Test.one:
      return 'hello';
    case Test.two:
      return {};

    default:
      exhaustive(n);
      throw new Error('hi');
  }
};

const b = play(Test.one);

//
console.log(b);

Может ли кто-нибудь помочь мне понять, почему Typescript не может сделать вывод, что тип возвращаемого значения play(Test.one) является строкой, а не объектом? Кроме того, если есть что-то, что я могу сделать, чтобы заставить его работать, я тоже хотел бы знать об этом.

Typescript 3.9.4

При наведении курсора на typeof b получается: неверный предполагаемый тип

Ответы [ 2 ]

1 голос
/ 08 июля 2020

Typescript не будет пытаться точно вывести что-либо подобное (в основном вывести перегрузки на основе операторов switch). Лучшее, на что вы можете надеяться от вывода TS, - это объединение всех возможных возвращаемых типов. В вашем случае вы получаете тип возвращаемого значения как {}, потому что большинство типов совместимы с {}, даже string, поэтому объединение {} | string упрощается до {}.

Единственное решение здесь - четко указывать типы возвращаемых значений с использованием нескольких перегрузок (хотя вам потребуется объявление функции, перегрузки не могут быть определены в выражении функции):

function play(n: Test.one): "hello"
function play(n: Test.two): {}
function play(n: Test) {
    switch (n) {
        case Test.one:
            return 'hello';
        case Test.two:
            return {};

        default:
            exhaustive(n);
            throw new Error('hi');
    }
};

const b = play(Test.one); // "hello"

Ссылка на игровую площадку

Примечание: ваша реализация не будет проверяться на соответствие перегрузкам, поэтому вы должны убедиться, что реализация и перегрузки согласуются.

1 голос
/ 08 июля 2020

Причина в том, что каждое возвращаемое значение имеет разный тип: одно возвращает строку, второе возвращает объект, а второе - ошибку. Таким образом, линтер выберет базовый класс - object

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...