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() {