处理可为空的类型时出现流错误

时间:2019-07-19 18:06:49

标签: redux flowtype

我正在研究具有以下状态的redux reducer:

 export type WishlistState = {
  +deals: ?DealCollection,
  +previousWishlist: ?(Deal[]),
  +currentWishlist: ?(Deal[]),
  +error: ?string
};
export type DealCollection = { [number]: Deal };

export const initialState: WishlistState = {
  deals: null,
  previousWishlist: null,
  currentWishlist: null,
  error: null
};

export default function wishlistReducer(
  state: WishlistState = initialState,
  action: WishlistAction
): WishlistState {
  switch (action.type) {
    case "GET_DEALS_SUCCESS":
      return { ...state, deals: action.deals };
    case types.GET_WISHLIST_SUCCESS:
      console.log(action);
      const currentWishlist: Deal[] = action.wishlistIds.map(
      // ATTENTION: THIS LINE HERE
        d => state.deals[d]
      );
      return {
        ...state,
        currentWishlist,
        previousWishlist: null,
        error: null
      };
    // ...other cases
    default:
      return state;
  }
}

我标记为注释的行在d中出现了流错误 括号:

Cannot get `state.deals[d]` because an index signature declaring the expected key/value type is missing in null or undefined.

发生这种情况的原因是类型注释:deals: ?DealCollection,如果我将行更改为以下内容,该注释会更清楚:

d => state.deals && state.deals[d]

将错误移至state.deals;想法是,如果state.deals为null,则该回调返回null(或未定义),这是map回调不可接受的返回类型。

我尝试了这个,我真的认为它会起作用:

      const currentWishlist: Deal[] = !state.deals
        ? []
        : action.wishlistIds.map(d => state.deals[d]);

如果没有deals为null,并且永远不会进行map调用,它将返回可接受的结果。但这会将错误放回到有关索引签名的[d]上。

在这种情况下,有什么方法可以让Flow开心吗?

1 个答案:

答案 0 :(得分:0)

只要变量已被修改,Flow都会使类型细化无效。在您的情况下,检查!state.deals的想法是一个好的开始;但是,Flow将使state.deals必须是DealCollection的事实无效,因为(理论上)您可以在map函数中对其进行修改。有关流类型无效的更多信息,请参见https://stackoverflow.com/a/43076553/11308639

就您而言,可以将state.deals细化为DealCollection来“缓存”。例如,

type Deal = string; // can be whatever
type DealCollection = { [number]: Deal };
declare var deals: ?DealCollection; // analogous to state.deals
declare var wishlistIds: number[]; // analogous to action.wishlistIds
let currentWishlist: Deal[] = [];
if (deals !== undefined && deals !== null) {
  const deals_: DealCollection = deals;
  currentWishlist = wishlistIds.map(d => deals_[d]);
}

Try Flow

通过这种方式,您可以访问deals_,而Flow不会使优化无效。