diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js index 9450f9222f..10bf26c0c8 100644 --- a/lib/util/propTypes.js +++ b/lib/util/propTypes.js @@ -41,7 +41,8 @@ function isFunctionType(node) { */ function isSuperTypeParameterPropsDeclaration(node) { if (node && (node.type === 'ClassDeclaration' || node.type === 'ClassExpression')) { - if (node.superTypeParameters && node.superTypeParameters.params.length > 0) { + const superTypeArguments = 'superTypeArguments' in node ? node.superTypeArguments : node.superTypeParameters; + if (superTypeArguments && superTypeArguments.params.length > 0) { return true; } } @@ -581,6 +582,19 @@ module.exports = function propTypesInstructions(context, components, utils) { ); } + /** + * Avoid deprecation errors around referencing typeParameters, while also + * maintain backwards-compatibility after typescript-eslint renamed + * `typeParameters` to `typeArguments` + * https://typescript-eslint.io/troubleshooting/faqs/general/#the-key-property-is-deprecated-on-type-nodes-use-key-instead-warnings + * @param {ASTNode} node The AST node being checked. + * @returns {any | undefined} Type parameters or arguments + */ + function getNodeTypeArguments(node) { + if (!node) return; + return 'typeArguments' in node ? node.typeArguments : node.typeParameters; + } + class DeclarePropTypesForTSTypeAnnotation { constructor(propTypes, declaredPropTypes, rootNode) { this.propTypes = propTypes; @@ -637,8 +651,8 @@ module.exports = function propTypesInstructions(context, components, utils) { typeName = node.typeName.name; const leftMostName = getLeftMostTypeName(node.typeName); const shouldTraverseTypeParams = genericReactTypesImport.has(leftMostName); - const nodeTypeParams = node.typeParameters; - if (shouldTraverseTypeParams && nodeTypeParams && nodeTypeParams.length !== 0) { + const nodeTypeArgs = getNodeTypeArguments(node); + if (shouldTraverseTypeParams && nodeTypeArgs && nodeTypeArgs.params.length !== 0) { // All react Generic types are derived from: // type PropsWithChildren

= P & { children?: ReactNode | undefined } // So we should construct an optional children prop @@ -660,7 +674,7 @@ module.exports = function propTypesInstructions(context, components, utils) { const idx = genericTypeParamIndexWherePropsArePresent[ leftMostName !== rightMostName ? rightMostName : importedName ]; - const nextNode = nodeTypeParams.params[idx]; + const nextNode = nodeTypeArgs.params[idx]; this.visitTSNode(nextNode); return; } @@ -749,10 +763,10 @@ module.exports = function propTypesInstructions(context, components, utils) { convertReturnTypeToPropTypes(node, rootNode) { // ReturnType should always have one parameter - const nodeTypeParams = node.typeParameters; - if (nodeTypeParams) { - if (nodeTypeParams.params.length === 1) { - let returnType = nodeTypeParams.params[0]; + const nodeTypeArgs = getNodeTypeArguments(node); + if (nodeTypeArgs) { + if (nodeTypeArgs.params.length === 1) { + let returnType = nodeTypeArgs.params[0]; // This line is trying to handle typescript-eslint-parser // typescript-eslint-parser TSTypeQuery is wrapped by TSTypeReference if (astUtil.isTSTypeReference(returnType)) { @@ -784,11 +798,11 @@ module.exports = function propTypesInstructions(context, components, utils) { case 'ObjectExpression': iterateProperties(context, res.properties, (key, value, propNode) => { if (propNode && propNode.argument && propNode.argument.type === 'CallExpression') { - const propNodeTypeParams = propNode.argument.typeParameters; - if (propNodeTypeParams) { - this.visitTSNode(propNodeTypeParams); + const propNodeTypeArgs = getNodeTypeArguments(propNode.argument); + if (propNodeTypeArgs) { + this.visitTSNode(propNodeTypeArgs); } else { - // Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types. + // Ignore this CallExpression return value since it doesn't have any typeArguments to let us know it's types. this.shouldIgnorePropTypes = true; return; } @@ -806,10 +820,10 @@ module.exports = function propTypesInstructions(context, components, utils) { }); break; case 'CallExpression': - if (res.typeParameters) { - this.visitTSNode(res.typeParameters); + if (getNodeTypeArguments(res)) { + this.visitTSNode(getNodeTypeArguments(res)); } else { - // Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types. + // Ignore this CallExpression return value since it doesn't have any typeArguments to let us know it's types. this.shouldIgnorePropTypes = true; } break; @@ -992,9 +1006,9 @@ module.exports = function propTypesInstructions(context, components, utils) { break; case 'GenericTypeAnnotation': if (propTypes.id.name === '$ReadOnly') { - const propTypeParams = propTypes.typeParameters; + const propTypeArgs = getNodeTypeArguments(propTypes); ignorePropsValidation = declarePropTypesForObjectTypeAnnotation( - propTypeParams.params[0], + propTypeArgs.params[0], declaredPropTypes ); } else { @@ -1034,8 +1048,8 @@ module.exports = function propTypesInstructions(context, components, utils) { if ( node.parent && node.parent.callee - && node.parent.typeParameters - && node.parent.typeParameters.params + && getNodeTypeArguments(node.parent) + && getNodeTypeArguments(node.parent).params && ( node.parent.callee.name === 'forwardRef' || ( node.parent.callee.object @@ -1045,9 +1059,9 @@ module.exports = function propTypesInstructions(context, components, utils) { ) ) ) { - const propTypesParams = node.parent.typeParameters; + const propTypesArguments = getNodeTypeArguments(node.parent); const declaredPropTypes = {}; - const obj = new DeclarePropTypesForTSTypeAnnotation(propTypesParams.params[1], declaredPropTypes, rootNode); + const obj = new DeclarePropTypesForTSTypeAnnotation(propTypesArguments.params[1], declaredPropTypes, rootNode); components.set(node, { declaredPropTypes: obj.declaredPropTypes, ignorePropsValidation: obj.shouldIgnorePropTypes, @@ -1093,7 +1107,7 @@ module.exports = function propTypesInstructions(context, components, utils) { if ( annotation && annotation.type !== 'TSTypeReference' - && annotation.typeParameters == null + && getNodeTypeArguments(annotation) == null ) { return; }