【问题标题】:Flow: Getting error when using Map流程:使用地图时出现错误
【发布时间】:2018-05-06 08:28:53
【问题描述】:

我刚刚开始在我的一个项目中使用 Facebook Flow 实现类型检查,并且遇到了一些问题。我正在尝试使用地图执行以下操作:

/* @flow */

let testMap: Map<string, Array<number>> = new Map();
let key: string = "testString";

if (!testMap.has(key)) {
  testMap.set(key, [])
}

testMap.get(key).push(1);

但我收到一条错误消息:

Cannot call `testMap.get(...).push` because property `push` is missing in undefined [1]

尝试流程中的示例: https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVMCmAXM3MDO2AsgIYAOAXGGeQDxEBOAlgHYDmANGAIKOOkAnnVYBXALYAjTIwB8ssAF4wrTEloAKAJQBuDDjABrTIOpM27JWABE+IgGVsLDtb2pmUMBoCEdkhQA6AAtSAg1jQS0tMABvVDA8Qn9yAIIccJNuAG0AXS1UAF90P1oA9nSIrQDyUQIgjQBGXVQgA

这当然是因为Map接口中的get函数定义为:

get(key: K): V | void;

但我希望 Flow 能够识别出密钥实际上是在上面设置的。

关于我应该如何更改代码以使 Flow 快乐的任何建议?

非常感谢!

【问题讨论】:

    标签: javascript flowtype static-typing


    【解决方案1】:

    正如您所提到的,这里的问题是您对Map.get 的调用可能会返回void,正如您在V | void 中看到的那样。

    Flow 没有机会知道您的密钥是否已定义,因为这可能会在运行时发生变化。

    因此在访问push方法之前需要检查返回值是否不是undefined

    const arr = testMap.get(key);
    
    if (arr) {
      arr.push(1)
    } else {
      // map "testMap" didn't contain a value for key "key"
    }
    

    flow repl 中的完整演示:https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVMCmAXM3MDO2AsgIYAOAXGGeQDxEBOAlgHYDmANGAIKOOkAnnVYBXALYAjTIwB8ssAF4wrTEloAKAJQBuDDjABrTIOpM27JWABE+IgGVsLDtb2pmUMBoCEdkhQA6AAtSAg1jQS0tMABvVDA8Qn9yAIIccJNuAG0AXS1UAF90AGM4ViIwUn4rP1oA9nSI3XQPLyrGaLiE9oDyUQIgjQBGfIKwTBg02PiwYGAwcQobWoprMAATZnXWAHJcUtZsUjZKsAA3UhhRTDAoOEYjExsI60KgA


    另一种方法是这样的:

    let arr = testMap.get(key);
    
    if (!arr) {
      arr = [];
      testMap.set(key, arr);
    }
    
    arr.push(1);
    

    【讨论】:

    • 值得注意的是,由于 Flow 是一个静态检查器,它在运行时判断可能发生的事情的能力有限。文档中的 Requirement Invalidations 解释了这个概念,即使 Flow 知道 has 是一个有效的访问器,映射的状态可能在 get 时已经改变。正如这个答案所述,解决方案是记录返回值并消除歧义。
    猜你喜欢
    • 1970-01-01
    • 2022-11-14
    • 2019-12-03
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多