Theodor
Theodor

Reputation: 5656

Get React propType name, type and isRequired

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

React component type

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

Answers (3)

Deeksha Gupta
Deeksha Gupta

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

Theodor
Theodor

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

M_rivermount
M_rivermount

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

Related Questions