@@ -4527,7 +4527,7 @@ namespace ts {
45274527 return links.resolvedType;
45284528 }
45294529
4530- function getStringLiteralType (text: string): StringLiteralType {
4530+ function getStringLiteralTypeForText (text: string): StringLiteralType {
45314531 if (hasProperty(stringLiteralTypes, text)) {
45324532 return stringLiteralTypes[text];
45334533 }
@@ -4537,10 +4537,10 @@ namespace ts {
45374537 return type;
45384538 }
45394539
4540- function getTypeFromStringLiteral (node: StringLiteral | StringLiteralTypeNode): Type {
4540+ function getTypeFromStringLiteralTypeNode (node: StringLiteralTypeNode): Type {
45414541 const links = getNodeLinks(node);
45424542 if (!links.resolvedType) {
4543- links.resolvedType = getStringLiteralType (node.text);
4543+ links.resolvedType = getStringLiteralTypeForText (node.text);
45444544 }
45454545 return links.resolvedType;
45464546 }
@@ -4583,7 +4583,7 @@ namespace ts {
45834583 case SyntaxKind.ThisType:
45844584 return getTypeFromThisTypeNode(node);
45854585 case SyntaxKind.StringLiteralType:
4586- return getTypeFromStringLiteral (<StringLiteralTypeNode>node);
4586+ return getTypeFromStringLiteralTypeNode (<StringLiteralTypeNode>node);
45874587 case SyntaxKind.TypeReference:
45884588 return getTypeFromTypeReference(<TypeReferenceNode>node);
45894589 case SyntaxKind.TypePredicate:
@@ -8790,7 +8790,7 @@ namespace ts {
87908790 // for the argument. In that case, we should check the argument.
87918791 if (argType === undefined) {
87928792 argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
8793- ? getStringLiteralType ((<StringLiteral>arg).text)
8793+ ? getStringLiteralTypeForText ((<StringLiteral>arg).text)
87948794 : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
87958795 }
87968796
@@ -8985,7 +8985,7 @@ namespace ts {
89858985 case SyntaxKind.Identifier:
89868986 case SyntaxKind.NumericLiteral:
89878987 case SyntaxKind.StringLiteral:
8988- return getStringLiteralType ((<Identifier | LiteralExpression>element.name).text);
8988+ return getStringLiteralTypeForText ((<Identifier | LiteralExpression>element.name).text);
89898989
89908990 case SyntaxKind.ComputedPropertyName:
89918991 const nameType = checkComputedPropertyName(<ComputedPropertyName>element.name);
@@ -9854,17 +9854,25 @@ namespace ts {
98549854 return aggregatedTypes;
98559855 }
98569856
9857- // TypeScript Specification 1.0 (6.3) - July 2014
9858- // An explicitly typed function whose return type isn't the Void or the Any type
9859- // must have at least one return statement somewhere in its body.
9860- // An exception to this rule is if the function implementation consists of a single 'throw' statement.
9857+ /*
9858+ *TypeScript Specification 1.0 (6.3) - July 2014
9859+ * An explicitly typed function whose return type isn't the Void or the Any type
9860+ * must have at least one return statement somewhere in its body.
9861+ * An exception to this rule is if the function implementation consists of a single 'throw' statement.
9862+ * @param returnType - return type of the function, can be undefined if return type is not explicitly specified
9863+ */
98619864 function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration, returnType: Type): void {
98629865 if (!produceDiagnostics) {
98639866 return;
98649867 }
98659868
9866- // Functions that return 'void' or 'any' don't need any return expressions.
9867- if (returnType === voidType || isTypeAny(returnType)) {
9869+ // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
9870+ if (returnType && (returnType === voidType || isTypeAny(returnType))) {
9871+ return;
9872+ }
9873+
9874+ // if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
9875+ if (!returnType && !compilerOptions.noImplicitReturns) {
98689876 return;
98699877 }
98709878
@@ -9874,13 +9882,14 @@ namespace ts {
98749882 return;
98759883 }
98769884
9877- if (func.flags & NodeFlags.HasExplicitReturn) {
9885+ if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
98789886 if (compilerOptions.noImplicitReturns) {
9879- error(func.type, Diagnostics.Not_all_code_paths_return_a_value);
9887+ error(func.type || func , Diagnostics.Not_all_code_paths_return_a_value);
98809888 }
98819889 }
98829890 else {
98839891 // This function does not conform to the specification.
9892+ // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
98849893 error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
98859894 }
98869895 }
@@ -9955,14 +9964,10 @@ namespace ts {
99559964 emitAwaiter = true;
99569965 }
99579966
9958- const returnType = node.type && getTypeFromTypeNode(node.type);
9959- let promisedType: Type;
9960- if (returnType && isAsync) {
9961- promisedType = checkAsyncFunctionReturnType(node);
9962- }
9963-
9964- if (returnType && !node.asteriskToken) {
9965- checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
9967+ const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
9968+ if (!node.asteriskToken) {
9969+ // return is not necessary in the body of generators
9970+ checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
99669971 }
99679972
99689973 if (node.body) {
@@ -9985,13 +9990,13 @@ namespace ts {
99859990 // check assignability of the awaited type of the expression body against the promised type of
99869991 // its return type annotation.
99879992 const exprType = checkExpression(<Expression>node.body);
9988- if (returnType ) {
9993+ if (returnOrPromisedType ) {
99899994 if (isAsync) {
99909995 const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member);
9991- checkTypeAssignableTo(awaitedType, promisedType , node.body);
9996+ checkTypeAssignableTo(awaitedType, returnOrPromisedType , node.body);
99929997 }
99939998 else {
9994- checkTypeAssignableTo(exprType, returnType , node.body);
9999+ checkTypeAssignableTo(exprType, returnOrPromisedType , node.body);
999510000 }
999610001 }
999710002
@@ -10607,8 +10612,7 @@ namespace ts {
1060710612 function checkStringLiteralExpression(node: StringLiteral): Type {
1060810613 const contextualType = getContextualType(node);
1060910614 if (contextualType && contextualTypeIsStringLiteralType(contextualType)) {
10610- // TODO (drosen): Consider using getTypeFromStringLiteral instead
10611- return getStringLiteralType(node.text);
10615+ return getStringLiteralTypeForText(node.text);
1061210616 }
1061310617
1061410618 return stringType;
@@ -12132,14 +12136,9 @@ namespace ts {
1213212136 }
1213312137
1213412138 checkSourceElement(node.body);
12135- if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
12136- const returnType = getTypeFromTypeNode(node.type);
12137- let promisedType: Type;
12138- if (isAsync) {
12139- promisedType = checkAsyncFunctionReturnType(node);
12140- }
12141-
12142- checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
12139+ if (!isAccessor(node.kind) && !node.asteriskToken) {
12140+ const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
12141+ checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
1214312142 }
1214412143
1214512144 if (produceDiagnostics && !node.type) {
0 commit comments