如何使用另一个 propType 接口定义的动态键和值来验证 propType 形状?

How can I validate a propType shape with dynamic keys and values already defined by another propType interface?

假设我有一个用户对象的道具类型接口:

const userPropType = shape({
  name: string,
  address: string,
  age: number    
});

然后我想验证 props 接收的 全局用户对象 ,它由几个单独的 用户对象 组成,其中键是随机数字 ID。 例如:

{
  3142: {
    name: 'Jonh Doe',
    address: 'Baker Street',
    age: 23 
  },
  4345: {
    name: 'Jane Doe',
    address: 'Fourth Avenue',
    age: 64 
  }
}

我知道我可以使用 Prop Type 自定义验证器毫无问题地验证数字键。但问题是:我如何使用自定义处理程序来验证我的全局用户对象,该处理程序可以动态验证密钥,但也可以根据我已经定义的 userPropType 接口验证值。

在这个简短的示例中,我可以轻松地检查自定义验证器上的每个用户属性,但是如果我们考虑一个真实的案例场景,我的用户对象可能有超过 50 个属性,那么自定义验证它们中的每一个,特别是当我已经为我的单个用户对象定义了 propType 时。

所以,这就是问题所在:是否可以在自定义验证器中使用已经定义的 prop 类型接口?

谢谢!

我看到这个问题还没有得到解答。因为我已经找到了解决方案,所以我在这里分享它,希望它可能对其他开发人员有任何帮助。

我已经实现了一个自定义验证器,它可以为我检查道具是否确实是我期望的格式。

澄清一下,我的 'users' 属性应该是一个带有数字键的对象(即使表示为字符串)并且具有三个属性:名称(字符串)、地址(字符串)和年龄(数字)。

这是我的自定义实现:

const usersObjectPropType = (
  propValue,
  key,
  componentName
) => {
  let isNotValid;
  const userKeys = Object.keys(propValue.users);
  const userValues = Object.values(propValue.users);
  const allKeysAreNumeric = userKeys.every(key => !Number.isNaN(Number(key)));
  userValues.forEach(user => {
    if (typeof user.name !== 'string') {
      isNotValid = ['name', 'string', user.name];
    } else if (typeof user.address !== 'string') {
      isNotValid = ['address', 'string', user.address];
    } else if (typeof user.age !== 'number') {
      isNotValid = ['age', 'number', user.age];
    }
  });

  if (!allKeysAreNumeric) {
    return new Error(
      `Invalid prop '${key}' supplied to ${componentName} component. The keys for the '${key}' object should have the type 'number'.`
    );
  }
  if (isNotValid) {
    return new Error(
      `Invalid prop in '${key}' object supplied to ${componentName} component. The type of '${
        isNotValid[0]
      }' attribute provided was '${typeof isNotValid[2]}' and a '${
        isNotValid[1]
      }' was expected.`
    );
  }
};

Child.propTypes = {
  users: usersObjectPropType
};

这是一个工作演示,您可以在其中更改 App 发送到子组件的道具类型,并在控制台上查看 PropType 错误:

https://stackblitz.com/edit/react-4sunky?file=src/App.js