1

你好,Stackoverflow 的人,

我正在尝试创建一个函数来防止代码在运行时执行,并且存在不正确的流类型。

我的理解是,在运行时执行此操作的方法是改进或检查类型是否与所需内容匹配,并使用 Flow 来密切注意在此过程中不会遗漏任何案例。

一个简单的情况是我有一个字符串输入,我想确认匹配枚举/联合类型。我可以按照我对文字的期望进行此工作,例如

    /* @flow */

    type typeFooOrBaa = "foo"| "baa"

    const catchType = (toCheck: string): void => {

        // Working check
      if (toCheck === "foo" || toCheck === "baa") {
        // No Flow errors
        const checkedValue: typeFooOrBaa = toCheck 

        // ... do something with the checkedValue
      }
    };

在这里试试

自然,我想避免嵌入文字。

我尝试过的一件事是等效的对象键测试,它不起作用:-( 例如

    /* @flow */

    type typeFooOrBaa = "foo"| "baa"
    const fooOrBaaObj = {"foo": 1, "baa": 2}


    const catchType = (toCheck: string): void => {

      // Non working check
      if (fooOrBaaObj[toCheck]) {
        /*
        The next assignment generates the following Flow error

        Cannot assign `toCheck` to `checkedVariable` because: Either string [1] is incompatible
        with string literal `foo` [2]. Or string [1] is incompatible with string literal `baa` [3].",
            "type"
        */
        const checkedVariable: typeFooOrBaa = toCheck  
      }  
    };

在这里试试

是否有可能在不必走完整的流程运行时路线的情况下实现这样的目标?如果是这样,最好怎么做?

谢谢你的帮助。

4

2 回答 2

2

一种似乎可行的方法是使用定义允许值的 const 对象,以:

  1. 使用 $keys 实用程序生成联合类型。
  2. 使用该联合类型创建一个映射对象,其中键是所需的输入(我们的案例字符串),值是“可能”需要改进的类型。

这是之前重新设计的示例,因此:

  • 设置类型,因为我们希望允许“foo”或“baa”,但没有其他。
  • 检测字符串何时被适当地细化以使其仅包含“foo”或“baa”。
  • 检测字符串何时可能包含预期之外的其他内容。

感谢@vkurchatkin的回答帮助我解决了这个问题(最后)。

/* @flow */

// Example of how to persuade Flow to detect safe adequately refined usage of a Union type 
// at runtime and its unsafe, inadequately refined counterparts.

const fooOrBaaObj =  {foo: 'foo', baa: 'baa'}

type typeFooOrBaa = $Keys<typeof fooOrBaaObj>
// NB: $Keys used inorder for the type definition to avoid aliasing typeFooOrBaa === string 
// which allows things like below to correctly spot problems.
//const testFlowSpotsBadDefition: typeFooOrBaa = "make_flow_barf"


const fooOrBaaMap: { [key:  string]: ?typeFooOrBaa } = fooOrBaaObj;
// NB: Use of the "?" maybe signifier in the definition a essential to inform Flow that indexing into 
// the map "might" produce a "null". Without it the subsequent correct detection of unsafe
// unrefined variables fails.



const catchType = (toCheck: string): void => {     
  const myValue = fooOrBaaMap[toCheck];
  if (myValue) {
    // Detects refined safe usage
    const checkedVariable: typeFooOrBaa = myValue  
  } 
  // Uncommenting the following line correctly causes Flow to flag the unsafe type. Must have the
  // "?" in the map defininiton to get Flow to spot this.
  //const testFlowSpotsUnrefinedUsage: typeFooOrBaa = myValue  
}

在这里玩一下

于 2019-01-24T14:32:47.737 回答
0

您可以将对象键入为{[fooOrBaa]: number},但 flow 不会强制 的所有成员都fooOrBaa存在于对象中。

于 2019-01-20T16:30:46.743 回答