Skip to content

Commit 05379a0

Browse files
committed
Warn on export expressions that are not React component (array, object, logical expression, ...) (fixes #26)
1 parent 8763332 commit 05379a0

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Support memo default export function components (fixes #27)
6+
- Warn on export expressions that are not React component (array, object, logical expression, ...) (fixes #26)
67

78
## 0.4.3
89

src/only-export-components.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ const invalid = [
135135
code: "export const foo = 4; export const Bar = () => {};",
136136
errorId: "namedExport",
137137
},
138+
{
139+
name: "Component and PascalCase variable",
140+
code: "export function Component() {}; export const Aa = 'a'",
141+
errorId: "namedExport",
142+
},
138143
{
139144
name: "Component and variable",
140145
code: "const foo = 4; const Bar = () => {}; export { foo, Bar };",

src/only-export-components.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,6 @@ export const onlyExportComponents: TSESLint.RuleModule<
8686
nonComponentExports.push(identifierNode);
8787
return;
8888
}
89-
if (
90-
!mayHaveReactExport &&
91-
possibleReactExportRE.test(identifierNode.name)
92-
) {
93-
mayHaveReactExport = true;
94-
}
9589
if (
9690
allowConstantExport &&
9791
init &&
@@ -101,12 +95,30 @@ export const onlyExportComponents: TSESLint.RuleModule<
10195
) {
10296
return;
10397
}
104-
if (
105-
!(isFunction ? possibleReactExportRE : strictReactExportRE).test(
106-
identifierNode.name,
107-
)
108-
) {
109-
nonComponentExports.push(identifierNode);
98+
if (isFunction) {
99+
if (possibleReactExportRE.test(identifierNode.name)) {
100+
mayHaveReactExport = true;
101+
} else {
102+
nonComponentExports.push(identifierNode);
103+
}
104+
} else {
105+
if (
106+
init &&
107+
// Switch to allowList?
108+
notReactComponentExpression.includes(init.type)
109+
) {
110+
nonComponentExports.push(identifierNode);
111+
return;
112+
}
113+
if (
114+
!mayHaveReactExport &&
115+
possibleReactExportRE.test(identifierNode.name)
116+
) {
117+
mayHaveReactExport = true;
118+
}
119+
if (!strictReactExportRE.test(identifierNode.name)) {
120+
nonComponentExports.push(identifierNode);
121+
}
110122
}
111123
};
112124

@@ -216,3 +228,20 @@ const canBeReactFunctionComponent = (init: TSESTree.Expression | null) => {
216228
}
217229
return false;
218230
};
231+
232+
type ToString<T> = T extends `${infer V}` ? V : never;
233+
const notReactComponentExpression: ToString<TSESTree.Expression["type"]>[] = [
234+
"ArrayExpression",
235+
"AwaitExpression",
236+
"BinaryExpression",
237+
"ChainExpression",
238+
"ConditionalExpression",
239+
"Literal",
240+
"LogicalExpression",
241+
"ObjectExpression",
242+
"TaggedTemplateExpression",
243+
"TemplateLiteral",
244+
"ThisExpression",
245+
"UnaryExpression",
246+
"UpdateExpression",
247+
];

0 commit comments

Comments
 (0)