86

What's the difference between PropTypes.objectOf and PropTypes.shape? In the PropTypes:

// An object with property values of a certain type
optionalObjectOf: PropTypes.objectOf(PropTypes.number)

vs

// An object taking on a particular shape
optionalObjectWithShape: PropTypes.shape({
  color: PropTypes.string,
  fontSize: PropTypes.number
})

When should I use objectOf and when should I use shape?

Penny Liu
  • 7,720
  • 5
  • 40
  • 66
DMac the Destroyer
  • 4,770
  • 5
  • 29
  • 54

2 Answers2

155

PropTypes.objectOf is used when describing an object whose properties are all the same type.

const objectOfProp = {
  latitude: 37.331706,
  longitude: -122.030783
}

// PropTypes.objectOf(PropTypes.number)

PropTypes.shape is used when describing an object whose keys are known ahead of time, and may represent different types.

const shapeProp = {
  name: 'Jane',
  age: 25
}

// PropTypes.shape({ name: PropTypes.string, age: PropTypes.number })
djfdev
  • 4,939
  • 2
  • 17
  • 36
  • 1
    hmm... ok I get that. I think my confusion is with a lack of imagination. Can you give an example of a good real-world use case for `PropTypes.objectOf`? – DMac the Destroyer Aug 21 '17 at 14:49
  • A use case would be an object that you do not know the names of the keys ahead of time. As long as you know what type the values will be, you can use `PropTypes.objectOf` to validate. – djfdev Aug 21 '17 at 23:03
  • 1
    Well, `objectOf` is for a dictionary object with same type for all values. – Tr1et Aug 23 '17 at 02:11
51

Just wanted to provide an example given the following object:

{
    petStore: {
        animals: {
           '23': { name: 'Snuffles', type: 'dog', age 13 }
           '29': { name: 'Mittens', type: 'cat', age: 7 }
        }
    }
}

ObjectOf and Shape

Used when an object could have different property names, but a consistent set of properties for each one:

const animalItemShape = {
    name: PropTypes.string,
    type: PropTypes.string,
    age: PropTypes.number
}

const petStoreShape = {
    animals: PropTypes.objectOf(PropTypes.shape(animalItemShape))
}

As you can see, animals is an object composed of multiple properties that each conform to the animalItemShape type.

Hope it helps!

Levi Fuller
  • 9,146
  • 4
  • 34
  • 41
  • I used `PropTypes.objectOf(PropTypes.shape({...}))` and it did not work - got a wrong warning saying that I was "passing an object but expected string" when I was passing a string. The [docs](https://reactjs.org/docs/typechecking-with-proptypes.html) say that `objectOf` is for "An object with property values of a certain type" like `PropTypes.number`. I think you just need `PropTypes.shape({...})` without the `objectOf`, which worked for me. – Albert Vila Calvo Jan 24 '20 at 17:37
  • @AlbertVilaCalvo If I had to guess, I'd imagine you may have accidentally passed an object as one of the properties that you set to the `PropTypes.string` type. What did your object look like? – Levi Fuller Feb 04 '20 at 05:23
  • 3
    I've just tried again: using `PropTypes.objectOf(PropTypes.shape({...}))` makes the wrong "Invalid prop..." red error appear, whereas `PropTypes.shape({...})` works perfect (no error is shown). Again, the docs say that `objectOf` should be used like `PropTypes.objectOf(PropTypes.number)` and is for "An object with property values of a certain type". It seems to me that wrapping `PropTypes.shape({...})` with `objectOf` is not needed - just use `PropTypes.shape({...})` directly. – Albert Vila Calvo Feb 04 '20 at 10:27
  • I am facing issue, when i use shape with or without objectOf, i get string instead of object `field: "{↵ type: 'text',↵ hintText: '',↵ required: false,}"` don't know whats doing wrong – Hanzla Habib Jan 07 '21 at 04:58