Skip to content

Commit

Permalink
Exclude fragment shorthand render props
Browse files Browse the repository at this point in the history
  • Loading branch information
merrywhether committed Sep 12, 2023
1 parent 10e8131 commit 9b08f41
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 29 deletions.
22 changes: 17 additions & 5 deletions packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts
Expand Up @@ -55,16 +55,28 @@ function isFunctionArgument(
}

/**
* Checks if a node is an expression in a JSX attribute assignment
* Checks if a node is a type-constrained JSX expression
* ```
* <Comp x={...} />
* <Foo x={() => {}} />
* <Bar>{() => {}}</Bar>
* <Baz {...props} />
* ```
*/
function isJSXAttribute(
function isTypedJSXExpression(
node: TSESTree.Node,
): node is TSESTree.JSXExpressionContainer | TSESTree.JSXSpreadAttribute {
return (
node.type === AST_NODE_TYPES.JSXExpressionContainer ||
(node.type === AST_NODE_TYPES.JSXExpressionContainer &&
// We exclude JSXFragment parents because TS improperly types fragment
// shorthands currently, and this can be simplified to just checking
// against JSXExpressionContainer without a parent check once the
// corresponding issue is resolved. In practice this just means that
// passing a function without a return type to a fragment shorthand will
// be a lint error now, a type and lint error once TS issue is fixed, and
// just a type error if/when these checks are removed after that.
// https://github.com/microsoft/TypeScript/issues/50429
(node.parent.type === AST_NODE_TYPES.JSXAttribute ||
node.parent.type === AST_NODE_TYPES.JSXElement)) ||
node.type === AST_NODE_TYPES.JSXSpreadAttribute
);
}
Expand All @@ -78,7 +90,7 @@ function isTypedParent(
isVariableDeclaratorWithTypeAnnotation(parent) ||
isPropertyDefinitionWithTypeAnnotation(parent) ||
isFunctionArgument(parent, callee) ||
isJSXAttribute(parent)
isTypedJSXExpression(parent)
);
}

Expand Down
140 changes: 116 additions & 24 deletions packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts
Expand Up @@ -182,11 +182,7 @@ class App {
},
// https://github.com/typescript-eslint/typescript-eslint/issues/7552
{
code: `
const Comp: FC = () => {
return <button onClick={() => {}} />;
};
`,
code: 'const foo = <button onClick={() => {}} />;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
Expand All @@ -195,11 +191,7 @@ const Comp: FC = () => {
},
},
{
code: `
const Comp: FC = () => {
return <Button on={{ click: () => {} }} />;
};
`,
code: 'const foo = <button on={{ click: () => {} }} />;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
Expand All @@ -208,11 +200,25 @@ const Comp: FC = () => {
},
},
{
code: `
const Comp: FC = () => {
return <button {...{ onClick: () => {} }} />;
};
`,
code: 'const foo = <button {...{ onClick: () => {} }} />;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
{
code: 'const foo = <Bar>{() => {}}</Bar>;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
{
code: 'const foo = <Bar>{{ on: () => {} }}</Bar>;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
Expand Down Expand Up @@ -1018,11 +1024,7 @@ const x: Foo = {
],
},
{
code: `
const Comp = (): JSX.Element => {
return <button onClick={() => {}} />;
};
`,
code: 'const foo = <button onClick={() => {}} />;',
options: [{ allowTypedFunctionExpressions: false }],
parserOptions: {
ecmaFeatures: {
Expand All @@ -1032,10 +1034,100 @@ const Comp = (): JSX.Element => {
errors: [
{
messageId: 'missingReturnType',
line: 3,
endLine: 3,
column: 30,
endColumn: 32,
line: 1,
endLine: 1,
column: 33,
endColumn: 35,
},
],
},
{
code: 'const foo = <button on={{ click: () => {} }} />;',
options: [{ allowTypedFunctionExpressions: false }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
errors: [
{
messageId: 'missingReturnType',
line: 1,
endLine: 1,
column: 27,
endColumn: 34,
},
],
},
{
code: 'const foo = <button {...{ onClick: () => {} }} />;',
options: [{ allowTypedFunctionExpressions: false }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
errors: [
{
messageId: 'missingReturnType',
line: 1,
endLine: 1,
column: 27,
endColumn: 36,
},
],
},
{
code: 'const foo = <Bar>{() => {}}</Bar>;',
options: [{ allowTypedFunctionExpressions: false }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
errors: [
{
messageId: 'missingReturnType',
line: 1,
endLine: 1,
column: 22,
endColumn: 24,
},
],
},
{
code: 'const foo = <Bar>{{ on: () => {} }}</Bar>;',
options: [{ allowTypedFunctionExpressions: false }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
errors: [
{
messageId: 'missingReturnType',
line: 1,
endLine: 1,
column: 21,
endColumn: 25,
},
],
},
{
code: 'const foo = <>{() => {}}</>;',
options: [{ allowTypedFunctionExpressions: true }],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
errors: [
{
messageId: 'missingReturnType',
line: 1,
endLine: 1,
column: 19,
endColumn: 21,
},
],
},
Expand Down

0 comments on commit 9b08f41

Please sign in to comment.