@@ -16853,31 +16853,23 @@ namespace ts {
1685316853 }
1685416854 }
1685516855
16856- function getTypePredicateForCall (node: CallExpression) {
16856+ function isCallWithEffects (node: CallExpression) {
1685716857 const links = getNodeLinks(node);
16858- if (links.resolvedTypePredicate === undefined) {
16859- links.resolvedTypePredicate = computeTypePredicateForCall(node) || noTypePredicate;
16860- }
16861- return links.resolvedTypePredicate === noTypePredicate ? undefined : links.resolvedTypePredicate;
16862- }
16863-
16864- function computeTypePredicateForCall(node: CallExpression) {
16865- // A call expression parented by an expression statement is a potential assertion. Other call
16866- // expressions are potential type predicate function calls.
16867- const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression) :
16868- node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) :
16869- undefined;
16870- if (funcType && funcType !== silentNeverType) {
16871- const apparentType = getApparentType(funcType);
16872- if (some(getSignaturesOfType(apparentType, SignatureKind.Call), hasTypePredicate)) {
16873- return getTypePredicateOfSignature(getResolvedSignature(node));
16874- }
16858+ if (links.isCallWithEffects === undefined) {
16859+ // A call expression parented by an expression statement is a potential assertion. Other call
16860+ // expressions are potential type predicate function calls.
16861+ const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression) :
16862+ node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) :
16863+ undefined;
16864+ const apparentType = funcType && getApparentType(funcType) || unknownType;
16865+ links.isCallWithEffects = some(getSignaturesOfType(apparentType, SignatureKind.Call), hasTypePredicateOrNeverReturnType);
1687516866 }
16876- return undefined ;
16867+ return links.isCallWithEffects ;
1687716868 }
1687816869
16879- function hasTypePredicate(signature: Signature) {
16880- return !!getTypePredicateOfSignature(signature);
16870+ function hasTypePredicateOrNeverReturnType(signature: Signature) {
16871+ return !!(getTypePredicateOfSignature(signature) ||
16872+ signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never);
1688116873 }
1688216874
1688316875 function reportFlowControlError(node: Node) {
@@ -17094,14 +17086,20 @@ namespace ts {
1709417086 }
1709517087
1709617088 function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined {
17097- const predicate = getTypePredicateForCall(flow.node);
17098- if (predicate && predicate.kind === TypePredicateKind.Assertion) {
17099- const flowType = getTypeAtFlowNode(flow.antecedent);
17100- const type = getTypeFromFlowType(flowType);
17101- const narrowedType = predicate.type ?
17102- narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) :
17103- narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]);
17104- return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
17089+ if (isCallWithEffects(flow.node)) {
17090+ const signature = getResolvedSignature(flow.node);
17091+ const predicate = getTypePredicateOfSignature(signature);
17092+ if (predicate && predicate.kind === TypePredicateKind.Assertion) {
17093+ const flowType = getTypeAtFlowNode(flow.antecedent);
17094+ const type = getTypeFromFlowType(flowType);
17095+ const narrowedType = predicate.type ?
17096+ narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) :
17097+ narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]);
17098+ return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
17099+ }
17100+ if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
17101+ return neverType;
17102+ }
1710517103 }
1710617104 return undefined;
1710717105 }
@@ -17690,8 +17688,9 @@ namespace ts {
1769017688 }
1769117689
1769217690 function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
17693- if (hasMatchingArgument(callExpression, reference)) {
17694- const predicate = getTypePredicateForCall(callExpression);
17691+ if (hasMatchingArgument(callExpression, reference) && isCallWithEffects(callExpression)) {
17692+ const signature = getResolvedSignature(callExpression);
17693+ const predicate = getTypePredicateOfSignature(signature);
1769517694 if (predicate && predicate.kind !== TypePredicateKind.Assertion) {
1769617695 return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
1769717696 }
@@ -23652,15 +23651,14 @@ namespace ts {
2365223651 return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes);
2365323652 }
2365423653
23655- function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
23656- if (!(func.flags & NodeFlags.HasImplicitReturn)) {
23657- return false;
23658- }
23654+ function isNeverFunctionCall(expr: Expression) {
23655+ return expr.kind === SyntaxKind.CallExpression && isCallWithEffects(<CallExpression>expr) && !!(getTypeOfExpression(expr).flags & TypeFlags.Never);
23656+ }
2365923657
23660- if (some((<Block> func.body).statements, statement => statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>statement)) ) {
23661- return false;
23662- }
23663- return true ;
23658+ function functionHasImplicitReturn( func: FunctionLikeDeclaration ) {
23659+ return !!(func.flags & NodeFlags.HasImplicitReturn) && !some((<Block>func.body).statements, statement =>
23660+ statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>statement) ||
23661+ statement.kind === SyntaxKind.ExpressionStatement && isNeverFunctionCall((<ExpressionStatement>statement).expression)) ;
2366423662 }
2366523663
2366623664 /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */
0 commit comments