首页 > 解决方案 > Flow 不允许我将具有更多属性的泛型传递给期望更少属性的子级

问题描述

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

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

因此,对于这样一个非常简单的泛型:

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 有更多的 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<{

这是一个流repl

标签: javascriptflowtype

解决方案


我向流程维护人员提出了这个要求,似乎我实际上已经很接近了。我只是缺少泛型类型上的加号。我想我已经尝试过了,但我显然错了。所以这是最终的泛型类型:

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

之所以需要如此多的 readonlies 是因为,flow 不能保证您不会向类型添加新字段,或者更糟的是,不会更改现有字段的类型。通过将它们标记为 RO 流,您可以传递“兼容”对象,因为可以保证该类型不会在接收函数的内部“损坏”。

这是GH的原始答案


推荐阅读