@@ -9815,13 +9815,19 @@ namespace ts {
9815
9815
// An explicitly typed function whose return type isn't the Void or the Any type
9816
9816
// must have at least one return statement somewhere in its body.
9817
9817
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
9818
+ // @param returnType - return type of the function, can be undefined if return type is not explicitly specified
9818
9819
function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration, returnType: Type): void {
9819
9820
if (!produceDiagnostics) {
9820
9821
return;
9821
9822
}
9822
9823
9823
- // Functions that return 'void' or 'any' don't need any return expressions.
9824
- if (returnType === voidType || isTypeAny(returnType)) {
9824
+ // Functions with explicitly specified return type which is either 'void' or 'any' don't need any return expressions.
9825
+ if (returnType && (returnType === voidType || isTypeAny(returnType))) {
9826
+ return;
9827
+ }
9828
+
9829
+ // if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
9830
+ if (!returnType && !compilerOptions.noImplicitReturns) {
9825
9831
return;
9826
9832
}
9827
9833
@@ -9831,13 +9837,14 @@ namespace ts {
9831
9837
return;
9832
9838
}
9833
9839
9834
- if (func.flags & NodeFlags.HasExplicitReturn) {
9840
+ if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
9835
9841
if (compilerOptions.noImplicitReturns) {
9836
- error(func.type, Diagnostics.Not_all_code_paths_return_a_value);
9842
+ error(func.type || func , Diagnostics.Not_all_code_paths_return_a_value);
9837
9843
}
9838
9844
}
9839
9845
else {
9840
9846
// This function does not conform to the specification.
9847
+ // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
9841
9848
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
9842
9849
}
9843
9850
}
@@ -9912,14 +9919,10 @@ namespace ts {
9912
9919
emitAwaiter = true;
9913
9920
}
9914
9921
9915
- const returnType = node.type && getTypeFromTypeNode(node.type);
9916
- let promisedType: Type;
9917
- if (returnType && isAsync) {
9918
- promisedType = checkAsyncFunctionReturnType(node);
9919
- }
9920
-
9921
- if (returnType && !node.asteriskToken) {
9922
- checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
9922
+ const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
9923
+ if (!node.asteriskToken) {
9924
+ // return is not necessary in the body of generators
9925
+ checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
9923
9926
}
9924
9927
9925
9928
if (node.body) {
@@ -9942,13 +9945,13 @@ namespace ts {
9942
9945
// check assignability of the awaited type of the expression body against the promised type of
9943
9946
// its return type annotation.
9944
9947
const exprType = checkExpression(<Expression>node.body);
9945
- if (returnType ) {
9948
+ if (returnOrPromisedType ) {
9946
9949
if (isAsync) {
9947
9950
const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member);
9948
- checkTypeAssignableTo(awaitedType, promisedType , node.body);
9951
+ checkTypeAssignableTo(awaitedType, returnOrPromisedType , node.body);
9949
9952
}
9950
9953
else {
9951
- checkTypeAssignableTo(exprType, returnType , node.body);
9954
+ checkTypeAssignableTo(exprType, returnOrPromisedType , node.body);
9952
9955
}
9953
9956
}
9954
9957
@@ -12088,14 +12091,9 @@ namespace ts {
12088
12091
}
12089
12092
12090
12093
checkSourceElement(node.body);
12091
- if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
12092
- const returnType = getTypeFromTypeNode(node.type);
12093
- let promisedType: Type;
12094
- if (isAsync) {
12095
- promisedType = checkAsyncFunctionReturnType(node);
12096
- }
12097
-
12098
- checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
12094
+ if (!isAccessor(node.kind) && !node.asteriskToken) {
12095
+ const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
12096
+ checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
12099
12097
}
12100
12098
12101
12099
if (produceDiagnostics && !node.type) {
0 commit comments