Use regular PropTypes checks inside a custom validator

575 Views Asked by At

I started out with a very simple PropTypes validation:

name: PropTypes.string.isRequired,

Now I need to only have string be required if a certain other condition is false, so:

name: ({name, otherProp}) => {
  if (otherProp === 'foo') return null;

  if (typeof name === 'string') return null;

  return new Error('Error');
}

Which is fine in this case, but what I'd really like to be able to do after the first check is run the regular PropTypes check for string.isRequired inside my custom validator, like maybe:

name: ({name, otherProp}) => {
  if (otherProp === 'foo') return null;

  return PropTypes.string.isRequired;
}

It seems like there should be a way to do this with PropTypes.checkPropTypes, but I can't figure it out.

2

There are 2 best solutions below

0
On

I discovered while poking around the code for Material UI a clever way to do something equivalent to this: parallel prop-types checks. They have a very simple utility function chainPropTypes which goes like this:

export default function chainPropTypes(propType1, propType2) {
  if (process.env.NODE_ENV === 'production') {
    return () => null;
  }

  return function validate(...args) {
    return propType1(...args) || propType2(...args);
  };
}

You use this to do a custom prop types check along with a standard check. For example like this:

  anchorEl: chainPropTypes(PropTypes.oneOfType([HTMLElementType, PropTypes.func]), (props) => {
    if (props.open && (!props.anchorReference || props.anchorReference === 'anchorEl')) {

// ...
0
On

You can write your own custom PropType which can take a PropType as an argument.

export const myCustomPropType = (propType, otherProp) => {
    return function validate(props, propName, ...rest) {
        const originalPropType =  propType(props, propName, ...rest);
        if (props[otherProp] === 'foo') return originalPropType;
        if (typeof props[propName] === 'string') return originalPropType;
        return new Error('Error');
    };
};

Usage

MyComponent.propTypes {
    myProp: myCustomPropType(PropTypes.string.isRequired, 'otherPropName')
}