From c524af5b7f62cd595c2afb32d075fc6e03891165 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 9f92f48..3969797 100644 --- a/__tests__/PropTypesDevelopmentReact15.js +++ b/__tests__/PropTypesDevelopmentReact15.js @@ -1012,7 +1012,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 e65c1d3..7977451 100644 --- a/__tests__/PropTypesDevelopmentStandalone-test.js +++ b/__tests__/PropTypesDevelopmentStandalone-test.js @@ -1086,7 +1086,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 1a5f759..534c478 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; } @@ -377,14 +381,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); }