Flow 不允许我将具有更多属性的泛型传递给期望更少属性的子级

Flow doesn't allow me to pass generics with more properties to child that expects less properties

我有一个在多个地方使用的通用类型。

有时我必须编写组件,这些组件采用相同泛型的略有不同的版本(基本上相同的泛型,但道具较少)。我希望能够将具有更多道具的对象传递给期望它们具有更少道具的组件,但流程不允许我这样做。

所以,对于像这样的非常简单的泛型:

export type Form<T: {} = {}> = {
  data: T,
}>

我应该可以这样传下去:


type MyData = $ReadOnly<{ cool: boolean, superCool: boolean }>

type MyOtherData = $ReadOnly<{ cool: boolean }>

type OProps = {
  form: Form<MyOtherData>,
}

const OPstuff = function(p:OProps){

  return <div>Soy yo</div>
}

type PProps = {
  form: Form<MyData>,
  stuff: string[]
}

const PPstuff = function(p:PProps){

  return <OPstuff form={p.form}></OPstuff>
}


但是flow抱怨parent one有更多的props,这应该不是问题。

起初我认为这可能是一个突变问题,毕竟这有道理,但是在将所有内容注释为只读之后我得到了同样的错误:

export type Form<T: $ReadOnly<{}> = {}> = $ReadOnly<{
  data: $ReadOnly<T>,
}>

错误:

28:   return <OPstuff form={p.form}>Soy puto</OPstuff>
                            ^ Cannot create `OPstuff` element because property `superCool` is missing in object type [1] but exists in object type [2] in type argument `T` [3] of property `form`. [prop-missing]
References:
13:   form: Form<MyOtherData>,
                 ^ [1]
22:   form: Form<MyData>,
                 ^ [2]
4: export type Form<T: $ReadOnly<{}> = {}> = $ReadOnly<{

Here is a flow repl

似乎 flow 正在直接比较对象属性以查看它们是否兼容,所以索引器可能是你的朋友

这是否适用于您的用例?

type MyOtherData = $ReadOnly<{ cool: boolean, [key: string]: any }>

try

我向流程维护者提出这个要求,看来我实际上已经非常接近了。我只是少了一个 plus sign on the generic type。我想我已经试过了,但我显然错了。所以这是最终的通用类型:

export type Form<+T: $ReadOnly<{}> = {}> = $ReadOnly<{
  data: $ReadOnly<T>,
}>

之所以需要那么多 readonlies 是因为,除此之外,flow 无法保证您不会向某个类型添加新字段,甚至更糟的是,不会更改现有字段的类型。通过将它们标记为 RO 流,您可以传递“兼容”对象,因为可以保证类型不会在接收函数的内部被“损坏”。

Here is the original answer on GH