代码之家  ›  专栏  ›  技术社区  ›  MOZGIII

流中的递归类型定义

  •  0
  • MOZGIII  · 技术社区  · 9 年前

    我尝试使用flow 0.53.1。你能帮我解释一下这种奇怪的行为吗?

    此代码示例:

    /* @flow */
    
    type AnySupportedType =
      | AnySupportedPrimitive
      | AnySupportedObject
      | AnySupportedArray;
    type AnySupportedArray = Array<AnySupportedType>;
    type AnySupportedObject = { [string]: AnySupportedType };
    type AnySupportedPrimitive = boolean | number | string | void;
    
    type DataID = string
    type Data = {
      id: DataID
    }
    
    const y: Data = { id: "123" }
    const x: AnySupportedType = y;
    

    17: const x: AnySupportedType = y;
                                    ^ object type. This type is incompatible with
    17: const x: AnySupportedType = y;
                 ^ union: AnySupportedPrimitive | AnySupportedObject | AnySupportedArray
    

    Link 流动。org基于web的示例。

    2 回复  |  直到 9 年前
        1
  •  1
  •   Nat Mote    9 年前

    实际上,这与可变性有关。Flow不允许此代码,因为您可以编写 x.id = 5 (在适当的类型细化之后),因为 AnySupportedType number

    要解决此问题,需要使对象属性协变,有效地使其只读:

    type AnySupportedObject = { +[string]: AnySupportedType };

    注意添加了 + .

    x .

    查看上的完整示例 try .

    https://flow.org/blog/2016/10/04/Property-Variance/

        2
  •  0
  •   Adam    9 年前

    答案是Flow有两种类型对象的方法。一,你的 AnySupportedObject ,将对象视为字典,您可以在其中通过任何键查找项目(类似于 Map<string, whatever> .

    另一种方式是作为记录,其中有一组特定的已知键,每个键可以指向其自己的值类型(例如, {a: number, b: string}

    这两种类型有非常不同的含义,尽管通常任何一种都可以应用于特定的对象。类型系统使它们保持不同,并强制您以某种方式处理对象,以避免生成类型错误。