From 3910873a2621a9f60a14d2ec5076a27e950e4eea Mon Sep 17 00:00:00 2001 From: Josh Alling Date: Thu, 19 Jul 2018 20:48:33 -0600 Subject: [PATCH] [New] `oneOfType`: Add expected types to warning Adds data object to returned error in checker so that the expected types can be accessed from within oneOfType check. Also, updates the tests slightly. Fixes #9. --- __tests__/PropTypesDevelopmentReact15.js | 2 +- .../PropTypesDevelopmentStandalone-test.js | 2 +- factoryWithTypeCheckers.js | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) 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); }