Reputation: 5656
I noticed that react components have a type.propTypes
object, which hold all propTypes as keys.
For instance,
Component.propTypes = { initialCount: React.PropTypes.number }
looks like
in Chrome dev tools. So I can get the name of the proptypes using
Object.keys(component.type.propTypes)
but can I also get the proptypes type and whether or not its required?
Upvotes: 3
Views: 2241
Reputation: 11
With propTypes API changed, PropTypes validators cannot be called directly. Types can be checked manually with checkPropTypes method of Proptypes.
Also the checkPropTypes does'nt returns any result, instead only logs the warnings to console. So, to retrieve the errors from type checking, check-prop-types is saviour. (Though there is a PR for facebook/prop-types, here, to allow external logging from checkPropTypes)
Here is an updated version of @Theodor's snippet (with slight changes):
import checkPropTypes from 'check-prop-types';
getPropType(propTypes, propName) {
let fakeProps = {};
fakeProps[propName] = "dummy";
let error = checkPropTypes(propTypes, fakeProps, 'prop');
// extract type from error string
if (error !== undefined) {
const EXPECTED_TYPE_PATTERN = /expected (\w+)/i;
return error.toString().match(EXPECTED_TYPE_PATTERN)[1];
} else {
// no error - it is string
return 'string';
}
}
getPropIsRequired(propTypes, propName){
let fakeProps = {};
fakeProps[propName] = null;
let error = checkPropTypes(propTypes,fakeProps);
return !!error;
};
extractTypes(component) {
let type_map = {};
let propTypes = component.type.propTypes;
Object.keys(propTypes).forEach((propName) => {
let type = getPropType(propTypes, propName);
let required = getPropsIsRequired(propTypes, propName)
type_map[propName]= {
type:type,
required:required
}
});
return type_map;
}
Upvotes: 0
Reputation: 5656
The following function extracts the propTypes' name, type and isRequired, based on @M_rivermount:s answer.
var extractPropTypes = (component) => {
let propTypes = component.type.propTypes;
let propNames = Object.keys(propTypes);
let extractPropType = (propTypes, propName) => {
let fakeProps = {};
fakeProps[propName] = "dummy";
let error = propTypes[propName](fakeProps, propName);
if (error === null) {
return "string";
} else {
const EXPECTED_TYPE_PATTERN = /expected `(\w+)`/i;
return error.toString().match(EXPECTED_TYPE_PATTERN)[1];
}
};
let extractPropIsRequired = (propTypes, propName) => {
let fakeProps = {};
fakeProps[propName] = null;
let error = propTypes[propName](fakeProps, propName);
return !!error;
};
return propNames.map(function (propName) {
return {
name: propName,
type: extractPropType(propTypes, propName),
isRequired: extractPropIsRequired(propTypes, propName)
}
});
};
Upvotes: 2
Reputation: 511
Not really. If you check ReactPropTypes.js the validation methods exported use an expectedType
within a private scope.
Also interesting to have a look at ReactElementValidator.js to see how it calls the propType validation.
If you wanted to test against the primitive types you could probably iterate calls with fake props to the validation method and catch errors until it does not throw, but I don't think that is what you were after.
Upvotes: 3