@@ -11808,10 +11808,42 @@ namespace ts {
1180811808 return aggregatedTypes;
1180911809 }
1181011810
11811+ function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
11812+ const expr = node.expression;
11813+ if (!node.possiblyExhaustive || expr.kind !== SyntaxKind.PropertyAccessExpression) {
11814+ return false;
11815+ }
11816+ const type = checkExpression((<PropertyAccessExpression>expr).expression);
11817+ if (!(type.flags & TypeFlags.Union)) {
11818+ return false;
11819+ }
11820+ const propName = (<PropertyAccessExpression>expr).name.text;
11821+ const propType = getTypeOfPropertyOfType(type, propName);
11822+ if (!propType || !isStringLiteralUnionType(propType)) {
11823+ return false;
11824+ }
11825+ const switchTypes = getSwitchClauseTypes(node);
11826+ if (!switchTypes.length) {
11827+ return false;
11828+ }
11829+ return eachTypeContainedIn(propType, switchTypes);
11830+ }
11831+
11832+ function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
11833+ if (!(func.flags & NodeFlags.HasImplicitReturn)) {
11834+ return false;
11835+ }
11836+ const lastStatement = lastOrUndefined((<Block>func.body).statements);
11837+ if (lastStatement && lastStatement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>lastStatement)) {
11838+ return false;
11839+ }
11840+ return true;
11841+ }
11842+
1181111843 function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] {
1181211844 const isAsync = isAsyncFunctionLike(func);
1181311845 const aggregatedTypes: Type[] = [];
11814- let hasReturnWithNoExpression = !! (func.flags & NodeFlags.HasImplicitReturn );
11846+ let hasReturnWithNoExpression = functionHasImplicitReturn (func);
1181511847 let hasReturnOfTypeNever = false;
1181611848 forEachReturnStatement(<Block>func.body, returnStatement => {
1181711849 const expr = returnStatement.expression;
@@ -11868,7 +11900,7 @@ namespace ts {
1186811900
1186911901 // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
1187011902 // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
11871- if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn )) {
11903+ if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !functionHasImplicitReturn (func)) {
1187211904 return;
1187311905 }
1187411906
0 commit comments