diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a53d9805..210c136a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel * [`jsx-fragments`], [`jsx-no-useless-fragment`]: avoid a crash on fragment syntax in `typescript-eslint` parser (@ljharb) * [`jsx-props-no-multi-spaces`]: avoid a crash on long member chains in tag names in `typescript-eslint` parser (@ljharb) * [`no-unused-prop-types`], `usedPropTypes`: avoid crash with typescript-eslint parser (@ljharb) +* [`display-name`]: unwrap TS `as` expressions ([#3110][] @ljharb) +[#3110]: https://github.com/yannickcr/eslint-plugin-react/pull/3110 [#3092]: https://github.com/yannickcr/eslint-plugin-react/pull/3092 [#2166]: https://github.com/yannickcr/eslint-plugin-react/pull/2166 [#1980]: https://github.com/yannickcr/eslint-plugin-react/pull/1980 diff --git a/lib/rules/display-name.js b/lib/rules/display-name.js index 9b2886d3d4..f444a2c6c5 100644 --- a/lib/rules/display-name.js +++ b/lib/rules/display-name.js @@ -5,6 +5,8 @@ 'use strict'; +const values = require('object.values'); + const Components = require('../util/Components'); const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); @@ -122,7 +124,6 @@ module.exports = { // -------------------------------------------------------------------------- return { - ClassProperty(node) { if (!propsUtil.isDisplayNameDeclaration(node)) { return; @@ -138,7 +139,7 @@ module.exports = { if (!component) { return; } - markDisplayNameAsDeclared(component.node); + markDisplayNameAsDeclared(component.node.type === 'TSAsExpression' ? component.node.expression : component.node); }, FunctionExpression(node) { @@ -215,7 +216,6 @@ module.exports = { // This means that we raise a single error for the call to React.memo // instead of one for React.memo and one for React.forwardRef const isWrappedInAnotherPragma = utils.getPragmaComponentWrapper(node); - if ( !isWrappedInAnotherPragma && (ignoreTranspilerName || !hasTranspilerName(node.arguments[0])) @@ -232,8 +232,8 @@ module.exports = { 'Program:exit'() { const list = components.list(); // Report missing display name for all components - Object.keys(list).filter((component) => !list[component].hasDisplayName).forEach((component) => { - reportMissingDisplayName(list[component]); + values(list).filter((component) => !component.hasDisplayName).forEach((component) => { + reportMissingDisplayName(component); }); }, }; diff --git a/tests/lib/rules/display-name.js b/tests/lib/rules/display-name.js index c81fe8f4c5..e0babc2076 100644 --- a/tests/lib/rules/display-name.js +++ b/tests/lib/rules/display-name.js @@ -520,6 +520,21 @@ ruleTester.run('display-name', rule, { }; `, }, + { + // issue 3032 + code: ` + const Comp = React.forwardRef((props, ref) =>
); + Comp.displayName = 'MyCompName'; + `, + }, + { + // issue 3032 + code: ` + const Comp = React.forwardRef((props, ref) =>
) as SomeComponent; + Comp.displayName = 'MyCompNameAs'; + `, + features: ['ts', 'no-babel'], + }, ]), invalid: parsers.all([