Flowtype: "object literal не может решить, какой случай выбрать" при использовании констант в действиях redux

РЕДАКТИРОВАТЬ: Ниже приведено полное репо GitHub минимального примера, показывающего проблему.

У меня есть простое приложение Counter. Вот мои создатели действия:

actions.js

/**
 * @flow
 */

import { INCREMENT, DECREMENT } from '../constants'

type Action =
  | { type: 'INCREMENT' }
  | { type: 'DECREMENT' }

function increment(): Action {
  return {
    type: INCREMENT
  }
}

function decrement(): Action {
  return {
    type: DECREMENT
  }
}

export { increment, decrement }
export type { Action }

В настоящее время я получаю ошибку как в функциях increment, так и decrement, которая гласит, что объектный литерал не может решить, какой случай выбрать тип объединения.

Чтобы исправить эти ошибки, я могу изменить type: INCREMENT на type: 'INCREMENT' и изменить type: DECREMENT на type: 'DECREMENT'. Тем не менее, я буду использовать эту константу в нескольких местах (например, редуктор), поэтому я надеялся, что смогу просто импортировать константу и использовать ее там. Не так ли это делается в потоковом режиме?

Для большей наглядности приведены остальные файлы:

constants.js

/**
 * @flow
 */

const INCREMENT: 'INCREMENT' = 'INCREMENT'
const DECREMENT: 'DECREMENT' = 'DECREMENT'

export {
  INCREMENT,
  DECREMENT
}

reducer.js

/**
 * @flow
 */

import { INCREMENT, DECREMENT } from '../constants'
import type { Action } from '../actions'

type State = number

function counter(state: State = 0, action: Action): State {
  switch (action.type) {
    case INCREMENT:
      return state + 1

    case DECREMENT:
      return state - 1

    default:
      return state
  }
}

export default counter

Изменить: Вот подробный журнал ошибок

src/actions/counter.js:12
              v
 12:   return {
 13:     type: INCREMENT
 14:   }
       ^ object literal. Could not decide which case to select
 11: function increment(): Action {
                           ^^^^^^ union type
  Case 1 may work:
    8:   | { type: 'INCREMENT' }
           ^^^^^^^^^^^^^^^^^^^^^ object type
  But if it doesn't, case 2 looks promising too:
    9:   | { type: 'DECREMENT' }
           ^^^^^^^^^^^^^^^^^^^^^ object type
  Please provide additional annotation(s) to determine whether case 1 works (or consider merging it with case 2):
   13:     type: INCREMENT
                 ^^^^^^^^^ identifier `INCREMENT`

src/actions/counter.js:18
              v
 18:   return {
 19:     type: DECREMENT
 20:   }
       ^ object literal. Could not decide which case to select
 17: function decrement(): Action {
                           ^^^^^^ union type
  Case 1 may work:
    8:   | { type: 'INCREMENT' }
           ^^^^^^^^^^^^^^^^^^^^^ object type
  But if it doesn't, case 2 looks promising too:
    9:   | { type: 'DECREMENT' }
           ^^^^^^^^^^^^^^^^^^^^^ object type
  Please provide additional annotation(s) to determine whether case 1 works (or consider merging it with case 2):
   19:     type: DECREMENT
                 ^^^^^^^^^ identifier `DECREMENT`

Ответ 1

Попробуйте добавить typeof в ваше объявление действий:

type Action = 
  | { type: typeof INCREMENT } 
  | { type: typeof DECREMENT }

попробуйте протестировать здесь

Также вы можете использовать $Keys

const ActionTypes = {
  INCREMENT: 'INCREMENT',
  DECREMENT: 'DECREMENT'
}

type Action = { type: $Keys<typeof ActionTypes> } 

это выглядит менее подробным

дополнительная информация здесь: https://github.com/facebook/flow/issues/2377