首页 > 解决方案 > 您如何比较深层嵌套对象上的 $Shape 流?

问题描述

我遇到的问题是我想创建一个函数,该函数将一个对象作为较大对象的一小部分并深度合并它。但是,我希望它是强类型的,以捕捉“大”对象的形状是否发生变化。

我在下面包括一个人为的例子。

/* @flow */

type ContrivedType = {
  nested: {
    name: string,
    optionalValue1?: string,
    optionalValue2?: string,
  }
}

let contrived: ContrivedType = {
  nested: {name: "Required Value"}
}

type UpdateObject = $Shape<ContrivedType>

const update = (updateObject: UpdateObject): void => {
  contrived = {
    ...contrived, 
    ...updateObject,
    nested: {
      ...contrived?.nested, 
      ...updateObject?.nested
    }
  }
}

update({nested: {name: "should work", optionalValue1: "should work"}})
update({nested: {optionalValue1: "won't work"}})

在这里你可以看到结果

Cannot call 'update' with object literal bound to 'updateObject' because property 'name' is missing in object literal [1] but exists in object type [2] in property 'nested'. [prop-missing]

我怎样才能使这项工作?

标签: reactjstypesflowtypeflow

解决方案


您可以创建自己的$DeepShape类型,如在此处使用的那样

我使用的代码是

type $DeepShape<O: Object> = Object & $Shape<$ObjMap<O, (<V: Object>(V) => $DeepShape<V>) | (<V>(V) => V)>>

并且来自这个 Github 线程

这是上面代码的最终结果:

/* @flow */

type ContrivedType = {
  nested: {
    name: string,
    optionalValue1?: string,
    optionalValue2?: string,
  }
}

let contrived: ContrivedType = {
  nested: {name: "Required Value"}
}

type $DeepShape<O: Object> = Object & $Shape<$ObjMap<O, (<V: Object>(V) => $DeepShape<V>) | (<V>(V) => V)>>

type UpdateObject = $DeepShape<ContrivedType>

const update = (updateObject: UpdateObject): void => {
  contrived = {
    ...contrived, 
    ...updateObject,
    nested: {
      ...contrived?.nested, 
      ...updateObject?.nested
    }
  }
}

update({nested: {name: "should work", optionalValue1: "should work"}})
update({nested: {optionalValue1: "won't work"}})

希望对人们可能遇到的任何问题或疑虑提供任何反馈。


推荐阅读