【问题标题】:Flow: Object type with no parameter can't be assigned to object type with optional parameter流:不带参数的对象类型不能分配给带可选参数的对象类型
【发布时间】:2019-07-22 21:55:13
【问题描述】:

在使用流类型时,我认为应该可以将没有特定参数的类型的对象分配给具有可选参数的类型的变量。事实并非如此。

请看下面的代码...

// @flow

type T1 = {
  +a: string,
  +b? : number,
};

type T2 = {
  +a: string,
}

const t2: T2 = {
  a: "Hello",
};

const v1 : T1 = t2;    // ERROR!!! (Why???)

const v2 : T1 = {      // THIS WORKS
  ...t2
};

既然在 T1 中,'b' 属性是可选的,为什么 Flow 会阻止我分配另一个类型,其中 'b' 被简单地省略了?这种限制似乎没有必要且无益。

有没有人了解这种行为背后的基本原理,或者可以指出一些解释它的文档。我已经阅读了 Flow Objects 部分,但没有发现任何内容:https://flow.org/en/docs/types/objects/

【问题讨论】:

  • Flow 将抛出错误“无法将t2 分配给v1,因为T2 [1] 中缺少属性b,但T1 [2] 中存在。”这是正常和正确的。 bT1 类型的可选属性,但T1 类型不同于T2 类型。嗯看看flow.org/try/…

标签: javascript flowtype


【解决方案1】:

离开@Marko Savic's answer:

不精确的对象类型失败,因为 Flow 无法知道 b 类型的对象 T2 将具有什么类型的属性。例如,我们可以有const bad_t2: T2 = { a: 'string', b: 'also string' }。这应该清楚地表明,我们不能将bad_t2 分配给T1 类型的变量,因为bstring 类型,这与T1 的定义冲突。但是,当使T2 精确时,Flow 可以保证属性b 不会位于T2 类型的对象上,因此不会与T1 冲突。

【讨论】:

    【解决方案2】:

    正如我在 cmets 内部所说的,T1T2 是两种不同的类型,因为 T1 有一个可选的 prop b

    type T1 = {
      +a: string,
      +b?: number,
    }
    
    type T2 = {
      +a: string,
    }
    
    const t2: T2 = {
      a: "Hello",
    };
    
    const v1 : T1 = t2;
    

    流程错误:

    无法将t2 分配给v1,因为T2 中缺少属性b 但在T1 中存在。 这是正确的!

    解决方案是使用exact typeT2

    type T2 = {|
      +a: string,
    |}
    

    看看Exact object types

    现在,当您将 T2 作为确切对象时,您可以说:

    const v1 : T1 = t2; // THAT'S OK!
    

    因为t2 满足T1 类型的最小表示。

    FlowTry Example

    【讨论】:

    • 需要注意的一点是,不精确的对象类型会失败,因为 Flow 无法知道 b 类型的对象 T2 将具有什么类型的属性。例如,我们可以有const bad_t2: T2 = { a: 'string', b: 'also string' }。这应该清楚地表明,我们不能将bad_t2 分配给T1 类型的变量,因为bstring 类型,这与T1 的定义冲突。但是,当使T2 精确时,Flow 可以保证属性b 不会位于T2 类型的对象上,因此不会与T1 冲突。
    • @user11307804 这实际上正是我正在寻找的答案 - 为什么禁止分配是有意义的。是的,现在说得通了。如果您将评论移至某个答案,我会将其标记为已接受的答案。
    • @Marko Savic 我也很欣赏你的回答 - 不知道让它准确会导致它工作。谢谢。
    猜你喜欢
    • 2021-11-06
    • 2021-08-05
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2021-08-29
    • 2021-11-06
    • 1970-01-01
    相关资源
    最近更新 更多