Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There should be a way to validate the "shape" of an array. #230

Open
GreenGremlin opened this issue Oct 19, 2018 · 7 comments
Open

There should be a way to validate the "shape" of an array. #230

GreenGremlin opened this issue Oct 19, 2018 · 7 comments
Labels
new validator request Requests for a new kind of validator.

Comments

@GreenGremlin
Copy link

GreenGremlin commented Oct 19, 2018

It would be useful to have the ability to define the "shape" of an array prop. This could fairly easily be done by refactoring PropTypes.shape to take a shapeTypes argument of either an object or an array.

Example use case

const answers = loadAnswers();
/*
loadAnswers returns an array of key / value pairs.
[
  ['name', 'Foo Bar'],
  ['email', 'foo@email.com'],
  ['website', 'www.foo.com'],
];
*/
<UserForm answers={answers} />

UserForm.propTypes = {
  answers: PropTypes.arrayOf(PropTypes.shape([
    PropTypes.oneOf(['name', 'email', 'website']),
    PropTypes.string,
  ])),
}

Implementation wise, this should be as simple as updating the for...in loop in createShapeTypeChecker to be a for...of loop over the shapeTypes entries.

-       if (propType !== 'object') {
+       if (propType !== 'object' && propType !== 'array') {
          return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
        }
-       for (var key in shapeTypes) {
+       for (var [key, checker] of Object.entries(shapeTypes)) {
-         var checker = shapeTypes[key];

Of course this assumes support for Object.entries and destructuring, which I'm not sure this package is free to use. If not, then the implementation will be a little more complex, but certainly doable.

If this seems like a reasonable proposal, I can put up a PR.

@ljharb
Copy link
Collaborator

ljharb commented Oct 19, 2018

I'm confused; you want to validate that all items in an array match a validator? "shape" is for object properties, which arrays tend not to have.

@GreenGremlin
Copy link
Author

GreenGremlin commented Oct 19, 2018

I want to be able to define validation for the elements of an array in a way that position matters. In my example an answer is a key / value array. An answer has the "shape" [key, value] which is equivalent to {0: key, 1: value}. This makes sense, because in javascript arrays are just a special type of object.

@GreenGremlin GreenGremlin changed the title There should be a way to validate the shape of an array. There should be a way to validate the "shape" of an array. Oct 19, 2018
@ljharb
Copy link
Collaborator

ljharb commented Oct 19, 2018

Ah, i see, you want to make a propType for a "tuple".

I don't think it belongs in this project, but here's how you could do it using and and shape from airbnb-prop-types:

answers: and([PropTypes.array, shape({
  0: keyPropType.isRequired,
  1: valuePropType.isRequired,
  length: PropTypes.oneOf([2]).isRequired,
})])

(Arrays may be a special type of object, but conceptually they are quite different - arrays are lists, objects are bags of properties)

@GreenGremlin
Copy link
Author

Yes, a tuple is a good way to put it.

This is the solution I came up with, before filing this ticket, which doesn't require adding the airbnb-prop-types library.

function arrayOfShape(typeCheckers) {
  return PropTypes.arrayOf(
    (value, index, ...rest) => typeCheckers[index](value, index, ...rest)
  )
}

@ljharb
Copy link
Collaborator

ljharb commented Oct 19, 2018

sure, that works as well (altho it won't check the length).

@ljharb ljharb added the new validator request Requests for a new kind of validator. label Feb 21, 2019
@ljharb
Copy link
Collaborator

ljharb commented Feb 21, 2019

Related to #143.

@feonit
Copy link

feonit commented Apr 22, 2019

Best version of preview example:

function tuple(typeCheckers: Function[]) {
	return PropTypes.arrayOf(
		function (value, index, ...rest) {
			return typeCheckers[index].call(PropTypes, value, index, ...rest);
		}
	)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new validator request Requests for a new kind of validator.
Projects
None yet
Development

No branches or pull requests

3 participants