Skip to content

Commit

Permalink
fix(eslint-plugin): explicit-func-return-type: support object types a…
Browse files Browse the repository at this point in the history
…nd as expressions (#459)
  • Loading branch information
bradzacher authored and JamesHenry committed Apr 24, 2019
1 parent 4318a8b commit d19e512
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 7 deletions.
17 changes: 17 additions & 0 deletions packages/eslint-plugin/docs/rules/explicit-function-return-type.md
Expand Up @@ -98,6 +98,23 @@ let arrowFn: FuncType = () => 'test';
let funcExpr: FuncType = function() {
return 'test';
};

let asTyped = (() => '') as () => string;

interface ObjectType {
foo(): number;
}
let objectProp: ObjectType = {
foo: () => 1,
};

interface ObjectType {
foo(): number;
}

let asObjectProp = {
foo: () => 1,
} as ObjectType;
```

## When Not To Use It
Expand Down
44 changes: 37 additions & 7 deletions packages/eslint-plugin/src/rules/explicit-function-return-type.ts
Expand Up @@ -57,7 +57,6 @@ export default util.createRule<Options, MessageIds>({

/**
* Checks if a node is a setter.
* @param parent The node to check
*/
function isSetter(node: TSESTree.Node): boolean {
return (
Expand All @@ -67,7 +66,6 @@ export default util.createRule<Options, MessageIds>({

/**
* Checks if a node is a variable declarator with a type annotation.
* @param node The node to check
*/
function isVariableDeclaratorWithTypeAnnotation(
node: TSESTree.Node,
Expand All @@ -78,6 +76,38 @@ export default util.createRule<Options, MessageIds>({
);
}

/**
* Checks if a node belongs to:
* const x: Foo = { prop: () => {} }
*/
function isPropertyOfObjectVariableDeclaratorWithTypeAnnotation(
node: TSESTree.Node,
): boolean {
let parent = node.parent;
if (!parent || parent.type !== AST_NODE_TYPES.Property) {
return false;
}
parent = parent.parent;
if (!parent || parent.type !== AST_NODE_TYPES.ObjectExpression) {
return false;
}
parent = parent.parent;
return !!parent && isVariableDeclaratorWithTypeAnnotation(parent);
}

function isPropertyOfObjectInAsExpression(node: TSESTree.Node): boolean {
let parent = node.parent;
if (!parent || parent.type !== AST_NODE_TYPES.Property) {
return false;
}
parent = parent.parent;
if (!parent || parent.type !== AST_NODE_TYPES.ObjectExpression) {
return false;
}
parent = parent.parent;
return !!parent && parent.type === AST_NODE_TYPES.TSAsExpression;
}

/**
* Checks if a function declaration/expression has a return type.
* @param node The node representing a function.
Expand Down Expand Up @@ -117,15 +147,15 @@ export default util.createRule<Options, MessageIds>({
* @param {ASTNode} node The node representing a function.
*/
function checkFunctionExpressionReturnType(
node:
| TSESTree.ArrowFunctionExpression
| TSESTree.FunctionDeclaration
| TSESTree.FunctionExpression,
node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,
): void {
if (
options.allowTypedFunctionExpressions &&
node.parent &&
isVariableDeclaratorWithTypeAnnotation(node.parent)
(isVariableDeclaratorWithTypeAnnotation(node.parent) ||
isPropertyOfObjectVariableDeclaratorWithTypeAnnotation(node) ||
node.parent.type === AST_NODE_TYPES.TSAsExpression ||
isPropertyOfObjectInAsExpression(node))
) {
return;
}
Expand Down
Expand Up @@ -120,6 +120,29 @@ var funcExpr: Foo = function() { return 'test'; };
},
],
},
{
filename: 'test.ts',
code: `const x = (() => {}) as Foo`,
options: [{ allowTypedFunctionExpressions: true }],
},
{
filename: 'test.ts',
code: `
const x = {
foo: () => {},
} as Foo
`,
options: [{ allowTypedFunctionExpressions: true }],
},
{
filename: 'test.ts',
code: `
const x: Foo = {
foo: () => {},
}
`,
options: [{ allowTypedFunctionExpressions: true }],
},
],
invalid: [
{
Expand Down Expand Up @@ -260,5 +283,49 @@ class Test {
},
],
},

{
filename: 'test.ts',
code: `const x = (() => {}) as Foo`,
options: [{ allowTypedFunctionExpressions: false }],
errors: [
{
messageId: 'missingReturnType',
line: 1,
},
],
},
{
filename: 'test.ts',
code: `
interface Foo {}
const x = {
foo: () => {},
} as Foo
`,
options: [{ allowTypedFunctionExpressions: false }],
errors: [
{
messageId: 'missingReturnType',
line: 4,
},
],
},
{
filename: 'test.ts',
code: `
interface Foo {}
const x: Foo = {
foo: () => {},
}
`,
options: [{ allowTypedFunctionExpressions: false }],
errors: [
{
messageId: 'missingReturnType',
line: 4,
},
],
},
],
});

0 comments on commit d19e512

Please sign in to comment.