Skip to content

Commit

Permalink
feat(eslint-plugin): allow explicit variable type with arrow functions
Browse files Browse the repository at this point in the history
Fixes #149
  • Loading branch information
gilbsgilbs committed Feb 14, 2019
1 parent 1464696 commit 8a73cee
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
14 changes: 14 additions & 0 deletions packages/eslint-plugin/docs/rules/explicit-function-return-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ node.addEventListener('click', function() {});
const foo = arr.map(i => i * i);
```

### allowTypedFunctionExpressions

Examples of additional **correct** code for this rule with `{ allowTypedFunctionExpressions: true }`:

```ts
type FuncType = () => string;

let arrowFn: FuncType = () => 'test';

let funcExpr: FuncType = function() {
return 'test';
};
```

## When Not To Use It

If you don't wish to prevent calling code from using function return values in unexpected ways, then
Expand Down
26 changes: 23 additions & 3 deletions packages/eslint-plugin/src/rules/explicit-function-return-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as util from '../util';
type Options = [
{
allowExpressions?: boolean;
allowTypedFunctionExpressions?: boolean;
}
];
type MessageIds = 'missingReturnType';
Expand All @@ -32,6 +33,9 @@ export default util.createRule<Options, MessageIds>({
properties: {
allowExpressions: {
type: 'boolean'
},
allowTypedFunctionExpressions: {
type: 'boolean'
}
},
additionalProperties: false
Expand All @@ -40,7 +44,8 @@ export default util.createRule<Options, MessageIds>({
},
defaultOptions: [
{
allowExpressions: true
allowExpressions: true,
allowTypedFunctionExpressions: false
}
],
create(context, [options]) {
Expand All @@ -65,6 +70,17 @@ export default util.createRule<Options, MessageIds>({
);
}

/**
* Checks if the parent of a function expression has a type annotation.
* @param parent The parent of a function expression node
*/
function hasTypeAnnotation(parent: TSESTree.Node): boolean {
return (
parent.type === AST_NODE_TYPES.VariableDeclarator &&
!!parent.id.typeAnnotation
);
}

/**
* Checks if a function declaration/expression has a return type.
* @param node The node representing a function.
Expand All @@ -75,11 +91,15 @@ export default util.createRule<Options, MessageIds>({
| TSESTree.FunctionDeclaration
| TSESTree.FunctionExpression
): void {
if (node.returnType || !node.parent) return;

const checkTypeAnnotation =
options.allowTypedFunctionExpressions && hasTypeAnnotation(node.parent);

if (
!node.returnType &&
node.parent &&
!isConstructor(node.parent) &&
!isSetter(node.parent) &&
!checkTypeAnnotation &&
util.isTypeScriptFile(context.getFilename())
) {
context.report({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,28 @@ function test() {
allowExpressions: true
}
]
},
{
filename: 'test.ts',
code: `
var arrowFn: Foo = () => 'test';
`,
options: [
{
allowTypedFunctionExpressions: true
}
]
},
{
filename: 'test.ts',
code: `
var funcExpr: Foo = function() { return 'test'; };
`,
options: [
{
allowTypedFunctionExpressions: true
}
]
}
],
invalid: [
Expand Down Expand Up @@ -187,6 +209,30 @@ class Test {
column: 13
}
]
},
{
filename: 'test.ts',
code: `var arrowFn = () => 'test';`,
options: [{ allowTypedFunctionExpressions: true }],
errors: [
{
messageId: 'missingReturnType',
line: 1,
column: 15
}
]
},
{
filename: 'test.ts',
code: `var funcExpr = function() { return 'test'; };`,
options: [{ allowTypedFunctionExpressions: true }],
errors: [
{
messageId: 'missingReturnType',
line: 1,
column: 16
}
]
}
]
});

0 comments on commit 8a73cee

Please sign in to comment.