简体   繁体   English

流类型不适用于匿名函数中的外部作用域变量

[英]Flow type does not apply to outer scope variables within an anonymous function

I have a type defined for an action dispatched to a reducer: 我有一个为派发给reducer的动作定义的类型:

type RemoveQuestionAction = {
  type: 'REMOVE_QUESTION',
  questionId: number,
  docTypeId: number,
};

type QuestionAction =
  | RemoveQuestionAction
  | ...

The reducer checks the type of each action: 减速器检查每个动作的类型:

const questions = (
  state : QuestionState = defaultState,
  action : QuestionAction
) : QuestionState => {...};

The field questionId is referenced in a couple of array filters: 在几个数组过滤器中引用了字段questionId

  case REMOVE_QUESTION: {

    return {
      ...state,
      byId: state.allIds
                             // Throws error
        .filter(id => id !== action.questionId)
        .reduce((col, id) => ({
          ...col,
          [id]: state.byId[String(id)],
        }), {}),
                                               // Throws error
      allIds: state.allIds.filter(id => id !== action.questionId),
    };    
  }

This throws a type error for action.questionId . 这将为action.questionId引发类型错误。

However if the value from the action is placed in a variable, it is happy: 但是,如果将操作的值放在变量中,则很高兴:

  case REMOVE_QUESTION: {
    let { questionId } = action; // Ok with this

    return {
      ...state,
      byId: state.allIds
        .filter(id => id !== questionId)
        .reduce((col, id) => ({
          ...col,
          [id]: state.byId[String(id)],
        }), {}),
      allIds: state.allIds.filter(id => id !== questionId),
    };    
  }

Why can't I use the action 's value directly? 为什么我不能直接使用action的值?

Here is a REPL . 这是REPL

It performs as expected in the REPL, really strange as I can't see what could be different.. 它的性能达到了REPL的预期,真的很奇怪,因为我看不出有什么不同。

Flow is version 6.23 Flow是版本6.23

action.questionId throws an error because of refinement invalidation explained in the doc for type refinement . action.questionId抛出错误,因为文档中针对类型细化说明了细化无效。 Flow is not sure whether action is still RemoveQuestionAction or not when the arrow functions that are given to filter() are executed after the refinement by case REMOVE_QUESTION: . 当通过case REMOVE_QUESTION:细化之后执行了赋予filter()的箭头函数时,流程不确定action是否仍为RemoveQuestionAction

We humans know that filter() immediately executes the given callback function like id => id !== action.questionId so that action cannot be modified at all. 我们人类都知道filter() 立即执行给定的回调函数,例如id => id !== action.questionId因此根本无法修改action However, from flow's perspective, filter() is just a function that takes a callback function as an argument, and the callback function can be executed later like what addEventListener() does. 但是,从流的角度看, filter()只是一个将回调函数作为参数的函数,该回调函数可以addEventListener()一样稍后执行。 If the callback function can be executed later, there is a chance that action is modified and the type refinement no longer holds. 如果回调函数可以在以后执行,有一个机会, action修改和类型细化不再成立。 That's why flow invalidates the type refinement of action in such a case. 这就是为什么流无效的类型精action在这种情况下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM