ljharb / prop-types-tools

Custom React PropType validators
MIT License
671 stars 50 forks source link

Change API of mutuallyExclusiveProps to allow different prop types #24

Closed jerrysu closed 7 years ago

jerrysu commented 7 years ago

This modifies mutuallyExclusiveProps to define mutually exclusive props with different prop types. For example:

const iconOrImageUrl = mutuallyExclusiveProps({
  icon: iconProp,
  imageUrl: PropTypes.string,
});

I did this whilst allowing the old API to work, but I feel like something should be done to remove the old API. Let me know what your thoughts are about this...

@ljharb @backwardok

ljharb commented 7 years ago

hmm - i'd expect instead that you'd do:

icon: mutuallyExclusiveProps(iconProp, 'icon', 'imageURL'),
imageUrl: mutuallyExclusiveProps(PropTypes.string, 'icon', 'imageURL'),

why is this complexity necessary?

jerrysu commented 7 years ago

Oh interesting. I didn't realize that was how it was supposed to be used based on other examples I saw in the codebase. Will give it a shot!

ljharb commented 7 years ago

Happy to reopen this later if we still need this functionality :-)

merlinstardust commented 6 years ago

I did not understand how this was supposed to work until seeing this issue. The code needed seems to be a bit repetitive since you have to repeat the list for every prop you want to be exclusive.

I think could instead be a function that creates the propType definitions that then get spread into the main propTypes object.

I imagine it looking like this.

Component.propTypes = {
  ...mutuallyExclusiveProps({
    icon: iconProp,
    icon: PropTypes.string.isRequired,
  }),
  // other props here
};

As a simple workaround so you don't have to change the API, you could add a new PropType with the following definition, which wraps mutuallyExclusiveProps

exclusive = (propTypes) => {
  const names = Object.keys(propTypes);
  return names.reduce((object, name) => ({
    ...object,
    [name]: mutuallyExclusiveProps(propTypes[name], ...names)
  }), {});
};
ljharb commented 6 years ago

@merlinpatt see #21 as well.

Note that it's only repetitive if you define it inline; if you put it in a variable first, you can repeat the variable in the list trivially.