是否可以使用 PropTypes 来验证类字典对象?

Is it possible to use PropTypes to validate Dictionary-like objects?

我需要在我的 reducer 中验证类似字典的对象,但由于我已经在使用 Babel,所以我不想求助于 Typescript 等工具。

以这个对象为例:

posts : {
    byId : {
        "post1" : {
            id : "post1",
            author : "user1",
            body : "......",
            comments : ["comment1", "comment2"]    
        },
        "post2" : {
            id : "post2",
            author : "user2",
            body : "......",
            comments : ["comment3", "comment4", "comment5"]    
        }
    }
    allIds : ["post1", "post2"]
}

如何使用 PropTypes 表达我对 byId 对象的期望?可能吗?如果可以,怎么做?

使用PropTypes.shape()

posts: PropTypes.shape({
    byId: PropTypes.sth() // could be shape() or sth else
}),

如果使用 PropTypes' 内置道具类型无法实现您想要的效果,您可以编写自定义道具类型检查器。

如果您希望 byId 的所有值都是具有属性 idauthorbodycomments 的对象,您可以使用 shapeobjectOfarrayOf。如果你希望 allIds 包含 byId 的所有键,你可以编写一个自定义验证器:

posts: PropTypes.shape({
  byId: PropTypes.objectOf(PropTypes.shape({
    id: PropTypes.string,
    author: PropTypes.string,
    body: PropTypes.string,
    comments: PropTypes.arrayOf(PropTypes.string)
  })),
  allIds(props, propName, componentName) {
    if(!Object.keys(props.byId).every(postID => props[propName].includes(postID))) {
      return new Error('allIds must include all the ids provided to byId!');
    }
  }
})

上面使用了 shape,因此它需要一个带有键 byIdallIdsposts 对象。它期望 byId 是一个具有 属性 值的对象 也是一个形状的对象,具有 idauthorbody 是字符串, comments 是字符串数组。最后,它使用自定义 proptype 验证器检查 byId 中的每个键(post ID)是否存在于 allIds 中。如果没有,则抛出错误。但请注意,这不会涵盖 allIds 具有 post 个不存在于 byIds 中的情况。有关更多解决方案,请参阅 How to know if two arrays have the same values。您可以在必要时添加 isRequired