Created
August 25, 2020 15:36
-
-
Save tusbar/e0c911e304676af8d1bc7248ee5f943e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {checkPropTypes} from 'prop-types' | |
export function eitherRequired(propTypes) { | |
const names = Object.keys(propTypes) | |
const entries = Object.entries(propTypes) | |
const eitherOrType = type => (props, propName, componentName) => { | |
const used = names.filter(name => name in props) | |
if (used.length === 0) { | |
throw new Error(`One of the following properties is required in ${componentName}: ${names.join(', ')}`) | |
} | |
if (used.length > 1) { | |
throw new Error(`Only one of the following properties can be specified in ${componentName}: ${used.join(', ')}`) | |
} | |
if (type) { | |
return checkPropTypes({ | |
[propName]: type | |
}, props, propName, componentName) | |
} | |
return null | |
} | |
return Object.fromEntries( | |
entries.map(([name, type]) => [ | |
name, | |
eitherOrType(type) | |
]) | |
) | |
} | |
// Usage | |
MyComponent.propTypes = { | |
...eitherRequired({ | |
foo: PropTypes.string, | |
bar: PropTypes.exact({ | |
id: PropTypes.string.isRequired | |
}) | |
}), | |
baz: PropTypes.string.isRequired | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment