流为每个参数(action.location,action.weatherResult和action.error)抛出3个错误(找不到属性)。我发现的唯一解决方案是不合并,只有一个动作类型,其3个不同的属性可能是可选的,但这些属性不是可选的,因此无法解决我的问题。

动作

// @flow
import actionTypes from './index';

export type FetchWeatherStartAction = {
  type: string,
  location: string
};

export type FetchWeatherSuccessAction = {
  type: string,
  weatherResult: ?string
};

export type FetchWeatherFailAction = {
  type: string,
  error: string | false
};

export type WeatherAction = FetchWeatherStartAction | FetchWeatherSuccessAction | FetchWeatherFailAction;

const fetchWeatherStart = (location: string): FetchWeatherStartAction => ({
  type: actionTypes.WEATHER_FETCH_START,
  location
});

const fetchWeatherSuccess = (weatherResult: ?string): FetchWeatherSuccessAction => ({
  type: actionTypes.WEATHER_FETCH_SUCCESS,
  weatherResult
});

const fetchWeatherFail = (error: string | false): FetchWeatherFailAction => ({
  type: actionTypes.WEATHER_FETCH_FAIL,
  error
});

export {
  fetchWeatherStart,
  fetchWeatherSuccess,
  fetchWeatherFail
}


动作类型

// @flow
const actionTypes = {
  WEATHER_FETCH_START: 'WEATHER_FETCH_START',
  WEATHER_FETCH_SUCCESS: 'WEATHER_FETCH_SUCCESS',
  WEATHER_FETCH_FAIL: 'WEATHER_FETCH_FAIL'
}

export default actionTypes;


减速器

// @flow
import actionTypes from './../actions';
import type { WeatherAction } from './../actions/weather';

/*export type WeatherActionType = {
  type: string,
  error?: boolean | string,
  weatherResult?: string | null,
  location?: string
};*/

export type WeatherStateType = {
  location: string,
  fetchedFromServer: boolean,
  isFetching: boolean,
  fetchError: boolean | string,
  weatherResult: ?string
};

const defaultState: WeatherStateType = {
  location: 'Barcelona',
  fetchedFromServer: false,
  isFetching: false,
  fetchError: false,
  weatherResult: null
};

const weather = (state: WeatherStateType = defaultState, action: WeatherAction): WeatherStateType => {

  switch (action.type) {

    case actionTypes.WEATHER_FETCH_START:
      return {
        ...state,
        isFetching: true,
        fetchError: false,
        location: action.location
      };

    case actionTypes.WEATHER_FETCH_SUCCESS:
      return {
        ...state,
        fetchedFromServer: true,
        isFetching: false,
        fetchError: false,
        weatherResult: action.weatherResult
      };

    case actionTypes.WEATHER_FETCH_FAIL:
      return {
        ...state,
        fetchedFromServer: false,
        isFetching: false,
        fetchError: action.error
      };

    default:
      return state;
  }

};

export default weather;

最佳答案

您试图依靠类型中未实际编码的类型信息。

例如,在FetchWeatherStartAction的定义中:

export type FetchWeatherStartAction = {
  type: string,
  location: string
};


type被声明为string。任何字符串。

但是稍后,在这种切换情况下:

switch (action.type) {
    case actionTypes.WEATHER_FETCH_START:
        ...
        action.location
        ...


您期望Flow知道FetchWeatherStartActionWeatherAction枚举的唯一可能替代方法,该枚举可以将'WEATHER_FETCH_START'作为其type属性的值。仅基于类型,任何操作对其类型都可以具有任何值。我们唯一可以确定的是它是一个字符串。

解决方案是将操作变量定义为具有更具体的类型,并结合其法律价值。

export type FetchWeatherStartAction = {
  type: 'WEATHER_FETCH_START',
  location: string
};

export type FetchWeatherSuccessAction = {
  type: 'WEATHER_FETCH_SUCCESS',
  weatherResult: ?string
};

export type FetchWeatherFailAction = {
  type: 'WEATHER_FETCH_FAIL',
  error: string | false
};


当您检查type === 'WEATHER_FETCH_START'时,Flow可以确定实际类型为FetchWeatherStartAction。这是可能的,因为它已经知道actionWeatherActionWeatherAction是仅具有这三个可能值的枚举。

不幸的是,您不得不重复字符串文字,而不是引用常量。我知道人们对此感到不安,但在这种情况下,我会争辩说,将Flow的类型检查处理掉了将魔术常数视为不良习惯的所有原因。在Javascript中,使用语法标识符访问字段在语义上与通过其字符串名称访问字段没有区别。

07-24 17:48
查看更多