@@ -16853,31 +16853,23 @@ namespace ts {
16853
16853
}
16854
16854
}
16855
16855
16856
- function getTypePredicateForCall (node: CallExpression) {
16856
+ function isCallWithEffects (node: CallExpression) {
16857
16857
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);
16875
16866
}
16876
- return undefined ;
16867
+ return links.isCallWithEffects ;
16877
16868
}
16878
16869
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);
16881
16873
}
16882
16874
16883
16875
function reportFlowControlError(node: Node) {
@@ -17094,14 +17086,20 @@ namespace ts {
17094
17086
}
17095
17087
17096
17088
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
+ }
17105
17103
}
17106
17104
return undefined;
17107
17105
}
@@ -17690,8 +17688,9 @@ namespace ts {
17690
17688
}
17691
17689
17692
17690
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);
17695
17694
if (predicate && predicate.kind !== TypePredicateKind.Assertion) {
17696
17695
return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
17697
17696
}
@@ -23652,15 +23651,14 @@ namespace ts {
23652
23651
return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes);
23653
23652
}
23654
23653
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
+ }
23659
23657
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)) ;
23664
23662
}
23665
23663
23666
23664
/** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */
0 commit comments