diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 4a6b206ae6..08156171ab 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -64,7 +64,7 @@ function validateParams(p5, fn, lifecycles) { 'Boolean': z.boolean(), 'Function': z.function(), 'Integer': z.number().int(), - 'Number': z.number(), + 'Number': z.union([z.number(), z.literal(Infinity), z.literal(-Infinity)]), 'Object': z.object({}), 'String': z.string() }; @@ -414,31 +414,47 @@ function validateParams(p5, fn, lifecycles) { const processUnionError = error => { const expectedTypes = new Set(); let actualType; + let isActualTypeSet = false; - error.errors.forEach(err => { - const issue = err[0]; - if (issue) { - if (!actualType) { - actualType = issue.message; - } + const setActualType = (val) => { + if (!isActualTypeSet) { + actualType = val; + isActualTypeSet = true; + } + }; - if (issue.code === 'invalid_type') { - actualType = issue.message.split(', received ')[1]; - expectedTypes.add(issue.expected); + const processIssues = (issues, path) => { + if (!issues) return; + issues.forEach(err => { + const issue = err[0]; + if (issue) { + if (issue.code === 'invalid_union') { + processIssues(issue.errors, issue.path); + } else { + if (issue.code === 'invalid_type') { + setActualType(issue.message.split(', received ')[1]); + expectedTypes.add(issue.expected); + } else if (issue.code === 'invalid_value') { + expectedTypes.add('constant (please refer to documentation for allowed values)'); + setActualType(args[path[0]]); + } else if (issue.code === 'custom') { + const match = issue.message.match(/Input not instance of (\w+)/); + if (match) expectedTypes.add(match[1]); + setActualType(undefined); + } + } } - // The case for constants. Since we don't want to print out the actual - // constant values in the error message, the error message will - // direct users to the documentation. - else if (issue.code === 'invalid_value') { - expectedTypes.add('constant (please refer to documentation for allowed values)'); - actualType = args[error.path[0]]; - } else if (issue.code === 'custom') { - const match = issue.message.match(/Input not instance of (\w+)/); - if (match) expectedTypes.add(match[1]); - actualType = undefined; - } - } - }); + }); + }; + + processIssues(error.errors, error.path); + + if ( + expectedTypes.has('number') && + expectedTypes.has('constant (please refer to documentation for allowed values)') + ) { + expectedTypes.delete('constant (please refer to documentation for allowed values)'); + } if (expectedTypes.size > 0) { if (error.path?.length > 0 && args[error.path[0]] instanceof Promise) { diff --git a/test/unit/core/param_errors.js b/test/unit/core/param_errors.js index e37d2c4d8e..7e96cedc5c 100644 --- a/test/unit/core/param_errors.js +++ b/test/unit/core/param_errors.js @@ -279,4 +279,4 @@ suite('Validate Params', function () { assert.isFalse(result.success); }); }); -}); +}); \ No newline at end of file