diff --git a/src/rules/requireParameterType.js b/src/rules/requireParameterType.js index a0864fe2..a5ad0709 100644 --- a/src/rules/requireParameterType.js +++ b/src/rules/requireParameterType.js @@ -25,6 +25,19 @@ const create = iterateFunctionNodes((context) => { const excludeParameterMatch = new RegExp(_.get(context, 'options[0].excludeParameterMatch', 'a^')); return (functionNode) => { + // It is save to ignore FunctionTypeAnnotation nodes in this rule. + if (functionNode.type === 'FunctionTypeAnnotation') { + return; + } + + const isArrow = functionNode.type === 'ArrowFunctionExpression'; + const isArrowFunctionExpression = functionNode.expression; + const functionAnnotation = isArrow && _.get(functionNode, 'parent.id.typeAnnotation'); + + if (skipArrows === 'expressionsOnly' && isArrowFunctionExpression || skipArrows === true && isArrow) { + return; + } + _.forEach(functionNode.params, (identifierNode) => { const parameterName = getParameterName(identifierNode, context); @@ -32,13 +45,12 @@ const create = iterateFunctionNodes((context) => { return; } - const typeAnnotation = _.get(identifierNode, 'typeAnnotation') || _.get(identifierNode, 'left.typeAnnotation'); + let typeAnnotation; - const isArrow = functionNode.type === 'ArrowFunctionExpression'; - const isArrowFunctionExpression = functionNode.expression; + typeAnnotation = _.get(identifierNode, 'typeAnnotation') || _.get(identifierNode, 'left.typeAnnotation'); - if (skipArrows === 'expressionsOnly' && isArrowFunctionExpression || skipArrows === true && isArrow) { - return; + if (isArrow && functionAnnotation) { + typeAnnotation = true; } if (!typeAnnotation) { diff --git a/src/rules/requireReturnType.js b/src/rules/requireReturnType.js index 6cfba881..cd58cd1a 100644 --- a/src/rules/requireReturnType.js +++ b/src/rules/requireReturnType.js @@ -116,16 +116,13 @@ const create = (context) => { return; } + const returnType = functionNode.returnType || isArrow && _.get(functionNode, 'parent.id.typeAnnotation'); + if (isFunctionReturnUndefined && isReturnTypeAnnotationUndefined && !annotateUndefined) { context.report(functionNode, 'Must not annotate undefined return type.'); } else if (isFunctionReturnUndefined && !isReturnTypeAnnotationUndefined && annotateUndefined) { context.report(functionNode, 'Must annotate undefined return type.'); - } else if ( - !isFunctionReturnUndefined && - !isReturnTypeAnnotationUndefined && - annotateReturn && - !functionNode.returnType - ) { + } else if (!isFunctionReturnUndefined && !isReturnTypeAnnotationUndefined && annotateReturn && !returnType && !shouldFilterNode(functionNode)) { context.report(functionNode, 'Missing return type annotation.'); } }; diff --git a/tests/rules/assertions/requireParameterType.js b/tests/rules/assertions/requireParameterType.js index 63e02891..cbdb3d34 100644 --- a/tests/rules/assertions/requireParameterType.js +++ b/tests/rules/assertions/requireParameterType.js @@ -231,12 +231,18 @@ export default { { code: '(...foo: string) => {}' }, + { + code: 'const f: Foo = (a, b) => 42;' + }, { code: '({foo}: {foo: string}) => {}' }, { code: '([foo]: Array) => {}' }, + { + code: 'type fn = (a: string, b: number) => number;\nconst f: fn = (a, b) => {}' + }, { code: '(foo) => {}', settings: { diff --git a/tests/rules/assertions/requireReturnType.js b/tests/rules/assertions/requireReturnType.js index 40e3ec7f..fb7ec2a1 100644 --- a/tests/rules/assertions/requireReturnType.js +++ b/tests/rules/assertions/requireReturnType.js @@ -549,12 +549,18 @@ export default { { code: '(foo): string => {}' }, + { + code: 'const f: Foo = (a, b) => 42;' + }, { code: '(foo): string => {}', options: [ 'always' ] }, + { + code: 'type fn = (a: string, b: number) => number;\nconst f: fn = (a, b) => { return 42; }' + }, { code: '(foo) => { return; }' },