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([