Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I need to validate dictionary-like objects in my reducers, but since I'm already using Babel I don't want to resort to tools like Typescript.

Take this object as an example:

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

How could I express my expectations for the byId object using PropTypes? Is it possible? If so, how?

like image 437
eddy Avatar asked Jun 29 '17 22:06

eddy


1 Answers

You can write custom proptype checkers if you can't achieve what you wan't with PropTypes' builtin proptypes.

If you want an all the values of the byId to be objects with the properties id, author, body and comments, you can use shape, objectOf, and arrayOf. If you want allIds to include all the keys of byId you can write a custom validator:

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!');
    }
  }
})

The above uses shape so it expects a posts object with the keys byId and allIds. It expects byId to be an object with the property values to also be object of a shape, with id, author and body being strings, with comments being an array of strings. Finally, it uses a custom proptype validator that checks if every key in byId (the post IDs) exists in allIds. If not, then throw an error. Beware though, this won't cover the case that allIds has post IDs that don't exist in byIds. See How to know if two arrays have the same values for more solutions. You can add isRequired where necessary.

like image 140
Andrew Li Avatar answered Sep 22 '22 00:09

Andrew Li