@samitouri / QOS-React-2 / commits / d673e51044

Make PropType.object pass for Date and RegExp instances

8855d6153e252c735de0e6cc373787d22c1a467b gave more accurate error messages for date and regexp by returning 'date' and 'regexp' respectively from `getPropType`. However, for the object primitive check, which compares the instance passed with `getPropType's` return string, `object` !== 'date'. This adds special hanlding for those.

Cheng Lou committed Apr 11, 2014 at 16:36 UTC d673e510446e3c11a29aeb8e1e000733dd798094
2 files changed +43 -12
src/core/ReactPropTypes.js
+20 -6
@@ -113,11 +113,17 @@ function createChainableTypeChecker(validate) {
113
114 function createPrimitiveTypeChecker(expectedType) {
115 function validate(props, propName, componentName, location) {
116 - var propType = getPropType(props[propName]);
116 + var propValue = props[propName];
117 + var propType = getPropType(propValue);
118 if (propType !== expectedType) {
119 var locationName = ReactPropTypeLocationNames[location];
120 + // `propValue` being instance of, say, date/regexp, pass the 'object'
121 + // check, but we can offer a more precise error message here rather than
122 + // 'of type `object`'.
123 + var preciseType = getPreciseType(propValue);
124 +
125 return new Error(
120 - `Invalid ${locationName} \`${propName}\` of type \`${propType}\` ` +
126 + `Invalid ${locationName} \`${propName}\` of type \`${preciseType}\` ` +
127 `supplied to \`${componentName}\`, expected \`${expectedType}\`.`
128 );
129 }
@@ -275,13 +281,21 @@ function isRenderable(propValue) {
281 }
282 }
283
278 -// Equivalent of typeof but with special handling for arrays
284 +// Equivalent of `typeof` but with special handling for array.
285 function getPropType(propValue) {
286 var propType = typeof propValue;
287 + if (Array.isArray(propValue)) {
288 + return 'array';
289 + }
290 + return propType;
291 +}
292 +
293 +// This handles more types than `getPropType`. Only used for error messages.
294 +// See `createPrimitiveTypeChecker`.
295 +function getPreciseType(propValue) {
296 + var propType = getPropType(propValue);
297 if (propType === 'object') {
282 - if (Array.isArray(propValue)) {
283 - return 'array';
284 - } else if (propValue instanceof Date) {
298 + if (propValue instanceof Date) {
299 return 'date';
300 } else if(propValue instanceof RegExp) {
301 return 'regexp';
src/core/__tests__/ReactPropTypes-test.js
+23 -6
@@ -81,7 +81,7 @@ describe('Primitive Types', function() {
81 );
82 });
83
84 - it('should check for corner case JS types', function() {
84 + it('should fail date and regexp correctly', function() {
85 typeCheckFail(
86 PropTypes.string,
87 new Date(),
@@ -101,8 +101,10 @@ describe('Primitive Types', function() {
101 typeCheckPass(PropTypes.bool, false);
102 typeCheckPass(PropTypes.func, function() {});
103 typeCheckPass(PropTypes.number, 0);
104 - typeCheckPass(PropTypes.object, {});
104 typeCheckPass(PropTypes.string, '');
105 + typeCheckPass(PropTypes.object, {});
106 + typeCheckPass(PropTypes.object, new Date());
107 + typeCheckPass(PropTypes.object, /please/);
108 });
109
110 it("should be implicitly optional and not warn without values", function() {
@@ -272,24 +274,36 @@ describe('Component Type', function() {
274 describe('Instance Types', function() {
275 it("should warn for invalid instances", function() {
276 function Person() {}
275 - var name = Person.name || '<<anonymous>>';
277 +
278 typeCheckFail(
279 PropTypes.instanceOf(Person),
280 false,
281 'Invalid prop `testProp` supplied to `testComponent`, expected ' +
280 - 'instance of `' + name + '`.'
282 + 'instance of `Person`.'
283 );
284 typeCheckFail(
285 PropTypes.instanceOf(Person),
286 {},
287 'Invalid prop `testProp` supplied to `testComponent`, expected ' +
286 - 'instance of `' + name + '`.'
288 + 'instance of `Person`.'
289 );
290 typeCheckFail(
291 PropTypes.instanceOf(Person),
292 '',
293 'Invalid prop `testProp` supplied to `testComponent`, expected ' +
292 - 'instance of `' + name + '`.'
294 + 'instance of `Person`.'
295 + );
296 + typeCheckFail(
297 + PropTypes.instanceOf(Date),
298 + {},
299 + 'Invalid prop `testProp` supplied to `testComponent`, expected ' +
300 + 'instance of `Date`.'
301 + );
302 + typeCheckFail(
303 + PropTypes.instanceOf(RegExp),
304 + {},
305 + 'Invalid prop `testProp` supplied to `testComponent`, expected ' +
306 + 'instance of `RegExp`.'
307 );
308 });
309
@@ -300,6 +314,9 @@ describe('Instance Types', function() {
314
315 typeCheckPass(PropTypes.instanceOf(Person), new Person());
316 typeCheckPass(PropTypes.instanceOf(Person), new Engineer());
317 +
318 + typeCheckPass(PropTypes.instanceOf(Date), new Date());
319 + typeCheckPass(PropTypes.instanceOf(RegExp), /please/);
320 });
321
322 it("should be implicitly optional and not warn without values", function() {