Поток: выбор между действиями в редукторе - PullRequest
0 голосов
/ 10 июня 2018

TLDR: Я смоделировал свою проблему в Try Flow ( ссылка ).Не могли бы вы помочь мне решить эту проблему?

Полное описание проблемы:

В редукторе Redux я выбираю между тремя действиями.Одно действие может иметь любой тип, но его отличительной особенностью является то, что оно имеет определенное поле в своей полезной нагрузке (payload.entities.items в этом примере).Два других действия имеют определенные типы, чтобы отличать их друг от друга, а также имеют разные полезные нагрузки:

const FOO = 'FOO'
const BAR = 'BAR'

type ActionWithEntities = {|
  type: string,
  payload: {|
    entities: {|
      items: {
        [string]: string
      }
    |}
  |}
|}

type ActionWithFoo = {|
  type: typeof FOO,
  payload: {|
    foo: string
  |}
|}

type ActionWithBar = {|
  type: typeof BAR,
  payload: {|
    bar: string
  |}
|}

type Action =
  | ActionWithEntities
  | ActionWithFoo
  | ActionWithBar

В зависимости от действия, я хочу сделать все необходимое (не важно, что) в редукторе:

function reducer(state: State, action: Action) {
  if (action.payload && action.payload.entities && action.payload.entities.items) {
    return Object.assign({}, state, action.payload.entities.items);
  }

  switch(action.type) {
    case FOO:
      const foo = action.payload.foo;
      return { foo }
    case BAR: {
      const bar = action.payload.bar;
      return { bar }
    }
    default:
      return state;
  }
}

Моя проблема в том, что Flow не видит, что оператор if заботится о первом действии (потому что другие действия не имеют поля entities в своей полезной нагрузке), и жалуется внутриswitch утверждение, что поле, которое я пытаюсь использовать (foo или bar в этом примере), отсутствует в первом действии.

Какой правильный способ сделать Flow счастливым?

1 Ответ

0 голосов
/ 10 июня 2018

Поток причины не нравится, потому что поле типа ActionWithEntities имеет тип string, что означает, что оно может иметь значение FOO или BAR.Теперь ваша логика будет препятствовать попаданию переключателя / регистра, но поток не сможет следовать этой логике и уточнить тип.Одним из способов решения этой проблемы было бы явное указание поля типа для ActionWithEntities

Так что-то вроде

type ActionWithEntities = {|
  type: 'OTHER' | 'OTHER2' | 'OTHER3',
  payload: {|
    entities: {|
      items: {
        [string]: string
      }
    |}
  |}
|}
...