获取 React propType 名称、类型和 isRequired

Get React propType name, type and isRequired

我注意到 React 组件有一个 type.propTypes 对象,它将所有 propType 作为键。

例如,

Component.propTypes = { initialCount: React.PropTypes.number }

看起来像

在 Chrome 开发工具中。所以我可以使用

获取道具类型的名称
Object.keys(component.type.propTypes)

但我是否也可以获取 proptypes 类型以及是否需要它?

不是真的。如果您选中 ReactPropTypes.js,validation methods exported 在私有范围内使用 expectedType

看看 ReactElementValidator.js 看看它如何调用 propType validation 也很有趣。

如果你想针对原始类型进行测试,你可能可以使用伪造的道具迭代调用验证方法并捕获错误直到它不抛出,但我认为这不是你想要的。

以下函数根据@M_rivermount:s 回答提取 propTypes 的名称、类型和 isRequired。

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)
      }
  });
};

使用 PropTypes API changed, PropTypes validators cannot be called directly. Types can be checked manually with checkPropTypes Proptypes 方法。

此外,checkPropTypes 不会 returns 任何结果,而只会将警告记录到控制台。因此,要从类型检查中检索错误,check-prop-types is saviour. (Though there is a PR for facebook/prop-types, here,以允许从 checkPropTypes)

进行外部日志记录

这是@Theodor 片段的更新版本(略有改动):

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;
}