diff --git a/__tests__/PropTypesDevelopmentReact15.js b/__tests__/PropTypesDevelopmentReact15.js index 252eb93..d885d19 100644 --- a/__tests__/PropTypesDevelopmentReact15.js +++ b/__tests__/PropTypesDevelopmentReact15.js @@ -1080,7 +1080,7 @@ describe('PropTypesDevelopmentReact15', () => { typeCheckFail( PropTypes.oneOfType([PropTypes.string, PropTypes.number]), [], - 'Invalid prop `testProp` supplied to `testComponent`.', + 'Invalid prop `testProp` supplied to `testComponent`, expected one of type [string, number].', ); const checker = PropTypes.oneOfType([ diff --git a/__tests__/PropTypesDevelopmentStandalone-test.js b/__tests__/PropTypesDevelopmentStandalone-test.js index d16feec..a59cea8 100644 --- a/__tests__/PropTypesDevelopmentStandalone-test.js +++ b/__tests__/PropTypesDevelopmentStandalone-test.js @@ -1154,7 +1154,7 @@ describe('PropTypesDevelopmentStandalone', () => { typeCheckFail( PropTypes.oneOfType([PropTypes.string, PropTypes.number]), [], - 'Invalid prop `testProp` supplied to `testComponent`.', + 'Invalid prop `testProp` supplied to `testComponent`, expected one of type [string, number].', ); const checker = PropTypes.oneOfType([ diff --git a/factoryWithTypeCheckers.js b/factoryWithTypeCheckers.js index 45f2256..269e810 100644 --- a/factoryWithTypeCheckers.js +++ b/factoryWithTypeCheckers.js @@ -159,8 +159,9 @@ module.exports = function(isValidElement, throwOnDirectAccess) { * is prohibitively expensive if they are created too often, such as what * happens in oneOfType() for any type before the one that matched. */ - function PropTypeError(message) { + function PropTypeError(message, data) { this.message = message; + this.data = data && typeof data === 'object' ? data: {}; this.stack = ''; } // Make `instanceof Error` still work for returned errors. @@ -234,7 +235,10 @@ module.exports = function(isValidElement, throwOnDirectAccess) { // 'of type `object`'. var preciseType = getPreciseType(propValue); - return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); + return new PropTypeError( + 'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'), + {expectedType: expectedType} + ); } return null; } @@ -378,14 +382,19 @@ module.exports = function(isValidElement, throwOnDirectAccess) { } function validate(props, propName, componentName, location, propFullName) { + var expectedTypes = []; for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; - if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) { + var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret); + if (checkerResult == null) { return null; } + if (checkerResult.data.hasOwnProperty('expectedType')) { + expectedTypes.push(checkerResult.data.expectedType); + } } - - return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); + var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': ''; + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.')); } return createChainableTypeChecker(validate); }