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

Report the actual type when PropTypes.instanceOf fails #4622

Merged
merged 1 commit into from
Aug 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/isomorphic/classic/types/ReactPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,11 @@ function createInstanceTypeChecker(expectedClass) {
if (!(props[propName] instanceof expectedClass)) {
var locationName = ReactPropTypeLocationNames[location];
var expectedClassName = expectedClass.name || ANONYMOUS;
var actualClassName = getClassName(props[propName]);
return new Error(
`Invalid ${locationName} \`${propFullName}\` supplied to ` +
`\`${componentName}\`, expected instance of \`${expectedClassName}\`.`
`Invalid ${locationName} \`${propFullName}\` of type ` +
`\`${actualClassName}\` supplied to \`${componentName}\`, expected ` +
`instance of \`${expectedClassName}\`.`
);
}
return null;
Expand Down Expand Up @@ -412,4 +414,12 @@ function getPreciseType(propValue) {
return propType;
}

// Returns class name of the object, if any.
function getClassName(propValue) {
if (!propValue.constructor || !propValue.constructor.name) {
return '<<anonymous>>';
}
return propValue.constructor.name;
}

module.exports = ReactPropTypes;
45 changes: 29 additions & 16 deletions src/isomorphic/classic/types/__tests__/ReactPropTypes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ describe('ReactPropTypes', function() {
typeCheckFail(
PropTypes.arrayOf(PropTypes.number),
[1, 2, 'b'],
'Invalid prop `testProp[2]` of type `string` supplied to `testComponent`, ' +
'expected `number`.'
'Invalid prop `testProp[2]` of type `string` supplied to ' +
'`testComponent`, expected `number`.'
);
});

Expand All @@ -173,8 +173,8 @@ describe('ReactPropTypes', function() {
typeCheckFail(
PropTypes.arrayOf(PropTypes.instanceOf(Thing)),
[new Thing(), 'xyz'],
'Invalid prop `testProp[1]` supplied to `testComponent`, expected instance of `' +
name + '`.'
'Invalid prop `testProp[1]` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + name + '`.'
);
});

Expand Down Expand Up @@ -277,39 +277,52 @@ describe('ReactPropTypes', function() {
describe('Instance Types', function() {
it('should warn for invalid instances', function() {
function Person() {}
function Cat() {}
var personName = Person.name || '<<anonymous>>';
var dateName = Date.name || '<<anonymous>>';
var regExpName = RegExp.name || '<<anonymous>>';

typeCheckFail(
PropTypes.instanceOf(Person),
false,
'Invalid prop `testProp` supplied to `testComponent`, expected ' +
'instance of `' + personName + '`.'
'Invalid prop `testProp` of type `Boolean` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(Person),
{},
'Invalid prop `testProp` supplied to `testComponent`, expected ' +
'instance of `' + personName + '`.'
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(Person),
'',
'Invalid prop `testProp` supplied to `testComponent`, expected ' +
'instance of `' + personName + '`.'
'Invalid prop `testProp` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(Date),
{},
'Invalid prop `testProp` supplied to `testComponent`, expected ' +
'instance of `' + dateName + '`.'
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + dateName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(RegExp),
{},
'Invalid prop `testProp` supplied to `testComponent`, expected ' +
'instance of `' + regExpName + '`.'
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + regExpName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(Person),
new Cat(),
'Invalid prop `testProp` of type `Cat` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
);
typeCheckFail(
PropTypes.instanceOf(Person),
Object.create(null),
'Invalid prop `testProp` of type `<<anonymous>>` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
);
});

Expand Down Expand Up @@ -503,8 +516,8 @@ describe('ReactPropTypes', function() {
typeCheckFail(
PropTypes.objectOf(PropTypes.instanceOf(Thing)),
{a: new Thing(), b: 'xyz'},
'Invalid prop `testProp.b` supplied to `testComponent`, expected instance of `' +
name + '`.'
'Invalid prop `testProp.b` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + name + '`.'
);
});

Expand Down