тип объединения потока не выдает ошибку - PullRequest
0 голосов
/ 26 апреля 2018

Итак, у меня есть следующий код:

type Something =
  | { t: 'A', src: string }
  | { t: 'B', src: string }
  | { t: 'C', src: number };

const f = (o: Something): string => 
  o.t === 1
    ? o.src 
    : 'a-string';

Я ожидаю увидеть ошибку, когда вернусь o.src, когда o.t равно 1, поскольку я никогда не определял, что t может быть числом. Следовательно, поток не знает, какой тип o.src, если t это число. Но это работает без каких-либо ошибок. Что мне здесь не хватает?

Вот поток / попытка .

Для записи, Версия TypeScript правильно выдает ошибку. Хотя сообщение об ошибке не очень полезно.

Чтобы уточнить немного, если я вместо этого использую o.t === 'F', поток с радостью выдаст следующую ошибку:

9: ot === 'F' ^ все ветви несовместимы: любой объект со свойством t, совпадающим со строковым литералом F 1 , несовместим со строковым литералом A 2 . Или объект со свойством t, соответствующим строковому литералу F 1 , несовместим со строковым литералом B [3]. Или объект со свойством t, соответствующим строковому литералу F 1 , несовместим со строковым литералом C [4]. Рекомендации: 9: o.t === 'F' ^ 1 4: | {t: 'A', src: string} ^ 2 5: | {t: 'B', src: string} ^ [3] 6: | {t: 'C', src: number}; ^ [4]

Я не знаю почему, но это просто непоследовательное поведение, и я ожидаю увидеть некоторую ошибку, если я использую значение, которое не определено в типе. Вы знаете, как недоступный кусок кода.

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Flow обычно требует, чтобы вы использовали ==, так как в любом случае может рассказать вам о небезопасных принуждениях. Если вы напишите этот пример, используя ==, вы получите ошибку (ну, 4 ошибки), как и ожидалось:

const f = (o: Something): string => 
  o.t == 1
    ? o.src 
    : 'a-string';
0 голосов
/ 27 апреля 2018

Это до семантики ===. Согласно спецификации ECMA оператор определяется следующим образом (по крайней мере, важный бит):

Сравнение x === y, где x и y - значения, дает true или ложный. Такое сравнение выполняется следующим образом:

  1. Если тип (x) отличается от типа (y), вернуть false.
  2. ... другие шаги ...

На самом деле вам не нужно смотреть мимо шага 1. Ваше выражение o.t === 1 можно рассматривать как:

typeof o.t == typeof 1 && (...other steps...)

Только первая часть этого выражения будет когда-либо оценена, потому что оно может быть показано как ложное. Flow знает, что вы никогда не собираетесь сравнивать число со строкой здесь.

Поскольку другие люди ответили, вам следует использовать == вместо Flow.

0 голосов
/ 26 апреля 2018

Если вы проверите тип o.src на ? o.src, вы увидите, что он имеет тип "Пустой". Это означает, что поток понимает, что допустимый набор входных данных не должен приводить к выполнению этого кода. Flow не выдает ошибку, но понимает, что регистр невозможен, поэтому может быть возвращена только строка.

См. Ответ Питера Холла на , почему поток делает это. Похоже, что основной причиной является использование оператора ===. Первый шаг равенства ===, кажется, проверяет, является ли тип двух элементов одинаковым. Без того, чтобы они были одинаковыми, Flow отмечает, что ветка пуста. Кажется, что использование == может быть лучше для ловли этих вещей (если у вас включены предупреждения о небезопасном принуждении.)

Sidenote: если вы используете Flow.com/try, вы можете навести курсор на выражения, чтобы показать вам тип.

...