diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b69232437..5ff0e08075 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,14 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [`jsx-key`]: detect conditional returns ([#3630][] @yialo) * [`jsx-newline`]: prevent a crash when `allowMultilines ([#3633][] @ljharb) +### Changed +* [Refactor] `propTypes`: extract type params to var ([#3634][] @HenryBrown0) +* [Refactor] [`boolean-prop-naming`]: invert if statement ([#3634][] @HenryBrown0) +* [Refactor] [`function-component-definition`]: exit early if no type params ([#3634][] @HenryBrown0) +* [Refactor] [`jsx-props-no-multi-spaces`]: extract type parameters to var ([#3634][] @HenryBrown0) + [#3638]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3638 +[#3634]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3634 [#3633]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3633 [#3630]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3630 [#3623]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3623 diff --git a/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js index f1c7420a7f..b5dd37b529 100644 --- a/lib/rules/boolean-prop-naming.js +++ b/lib/rules/boolean-prop-naming.js @@ -240,19 +240,24 @@ module.exports = { } if ( - component.node.parent - && component.node.parent.type === 'VariableDeclarator' - && component.node.parent.id - && component.node.parent.id.type === 'Identifier' - && component.node.parent.id.typeAnnotation - && component.node.parent.id.typeAnnotation.typeAnnotation - && component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters - && ( - component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters.type === 'TSTypeParameterInstantiation' - || component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters.type === 'TypeParameterInstantiation' + !component.node.parent + || component.node.parent.type !== 'VariableDeclarator' + || !component.node.parent.id + || component.node.parent.id.type !== 'Identifier' + || !component.node.parent.id.typeAnnotation + || !component.node.parent.id.typeAnnotation.typeAnnotation + ) { + return; + } + + const annotationTypeParams = component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters; + if ( + annotationTypeParams && ( + annotationTypeParams.type === 'TSTypeParameterInstantiation' + || annotationTypeParams.type === 'TypeParameterInstantiation' ) ) { - return component.node.parent.id.typeAnnotation.typeAnnotation.typeParameters.params.find( + return annotationTypeParams.params.find( (param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation' ); } diff --git a/lib/rules/function-component-definition.js b/lib/rules/function-component-definition.js index e0a27dedca..f8a95a9da0 100644 --- a/lib/rules/function-component-definition.js +++ b/lib/rules/function-component-definition.js @@ -33,14 +33,12 @@ const UNNAMED_FUNCTION_TEMPLATES = { }; function hasOneUnconstrainedTypeParam(node) { - if (node.typeParameters) { - return ( - node.typeParameters.params.length === 1 - && !node.typeParameters.params[0].constraint - ); - } + const nodeTypeParams = node.typeParameters; - return false; + return nodeTypeParams + && nodeTypeParams.params + && nodeTypeParams.params.length === 1 + && !nodeTypeParams.params[0].constraint; } function hasName(node) { diff --git a/lib/rules/jsx-props-no-multi-spaces.js b/lib/rules/jsx-props-no-multi-spaces.js index b0d34d59dd..b9cabafe32 100644 --- a/lib/rules/jsx-props-no-multi-spaces.js +++ b/lib/rules/jsx-props-no-multi-spaces.js @@ -98,8 +98,12 @@ module.exports = { } function containsGenericType(node) { - const containsTypeParams = typeof node.typeParameters !== 'undefined'; - return containsTypeParams && node.typeParameters.type === 'TSTypeParameterInstantiation'; + const nodeTypeParams = node.typeParameters; + if (typeof nodeTypeParams === 'undefined') { + return false; + } + + return nodeTypeParams.type === 'TSTypeParameterInstantiation'; } function getGenericNode(node) { diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js index c5aa35eb61..a189f871ca 100644 --- a/lib/util/propTypes.js +++ b/lib/util/propTypes.js @@ -627,7 +627,8 @@ module.exports = function propTypesInstructions(context, components, utils) { typeName = node.typeName.name; const leftMostName = getLeftMostTypeName(node.typeName); const shouldTraverseTypeParams = genericReactTypesImport.has(leftMostName); - if (shouldTraverseTypeParams && node.typeParameters && node.typeParameters.length !== 0) { + const nodeTypeParams = node.typeParameters; + if (shouldTraverseTypeParams && nodeTypeParams && nodeTypeParams.length !== 0) { // All react Generic types are derived from: // type PropsWithChildren
= P & { children?: ReactNode | undefined }
// So we should construct an optional children prop
@@ -638,7 +639,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
const idx = genericTypeParamIndexWherePropsArePresent[
leftMostName !== rightMostName ? rightMostName : importedName
];
- const nextNode = node.typeParameters.params[idx];
+ const nextNode = nodeTypeParams.params[idx];
this.visitTSNode(nextNode);
return;
}
@@ -727,9 +728,10 @@ module.exports = function propTypesInstructions(context, components, utils) {
convertReturnTypeToPropTypes(node) {
// ReturnType