mutually exclusively require prop
sygint opened this issue · 2 comments
I have a component and it can take a prop of 'src' or children, but never both. I was unable to find a proptype supplied in this library to cover this.
@ljharb was helping me compose a prop-type for this and while it does seem to disallow the other prop if one is already provided, it doesn't also require that one exist.
here is the proposed prop-type:
static propTypes = {
src: disallowedIf(string, "children", any.isRequired),
children: disallowedIf(
oneOfType([arrayOf(node), node]),
"src",
any.isRequired
)
};
I am happy to contribute a solution for a mutulallyExclusivelyRequired or something similar if needs be.
Thanks!
I also ran into this problem, and ended up using the following solution:
const exclusivePropTypes = {
foo: fooValidator,
bar: barValidator,
baz: bazValidator
}
const exclusiveProps = Object.keys(exclusivePropTypes)
Component.propTypes = {
...Object.fromEntries(exclusiveProps.map(exclusiveProp => [
exclusiveProp,
AirbnbPropTypes.and([
exclusivePropTypes[exclusiveProp],
(props, propName, componentName, ...rest) => {
const propList = exclusiveProps.join(', ')
const exclusivePropCount = Object.keys(props)
.filter(prop => props[prop] != null)
.reduce((count, prop) => (count + (exclusivePropTypes[prop] ? 1 : 0)), 0)
if (exclusivePropCount > 1) {
return new Error(`A ${componentName} cannot have more than one of these props: ${propList}`)
}
if (exclusivePropCount < 1) {
return new Error(`A ${componentName} must have at least one of these props: ${propList}`)
}
}
])
]))
}
Ugh... we're just going to undertype things here if that's the alternative.