@@ -18790,6 +18790,22 @@ namespace ts {
18790
18790
return !(flow.flags & FlowFlags.PreFinally && (<PreFinallyFlow>flow).lock.locked) && isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ false);
18791
18791
}
18792
18792
18793
+ function isFalseExpression(expr: Expression): boolean {
18794
+ const node = skipParentheses(expr);
18795
+ if (node.kind === SyntaxKind.FalseKeyword) {
18796
+ return true;
18797
+ }
18798
+ if (node.kind === SyntaxKind.BinaryExpression) {
18799
+ if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
18800
+ return isFalseExpression((<BinaryExpression>node).left) || isFalseExpression((<BinaryExpression>node).right);
18801
+ }
18802
+ if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
18803
+ return isFalseExpression((<BinaryExpression>node).left) && isFalseExpression((<BinaryExpression>node).right);
18804
+ }
18805
+ }
18806
+ return false;
18807
+ }
18808
+
18793
18809
function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean {
18794
18810
while (true) {
18795
18811
if (flow === lastFlowNode) {
@@ -18809,8 +18825,17 @@ namespace ts {
18809
18825
}
18810
18826
else if (flags & FlowFlags.Call) {
18811
18827
const signature = getEffectsSignature((<FlowCall>flow).node);
18812
- if (signature && getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
18813
- return false;
18828
+ if (signature) {
18829
+ const predicate = getTypePredicateOfSignature(signature);
18830
+ if (predicate && predicate.kind === TypePredicateKind.AssertsIdentifier) {
18831
+ const predicateArgument = (<FlowCall>flow).node.arguments[predicate.parameterIndex];
18832
+ if (predicateArgument && isFalseExpression(predicateArgument)) {
18833
+ return false;
18834
+ }
18835
+ }
18836
+ if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
18837
+ return false;
18838
+ }
18814
18839
}
18815
18840
flow = (<FlowCall>flow).antecedent;
18816
18841
}
@@ -19049,6 +19074,9 @@ namespace ts {
19049
19074
19050
19075
function narrowTypeByAssertion(type: Type, expr: Expression): Type {
19051
19076
const node = skipParentheses(expr);
19077
+ if (node.kind === SyntaxKind.FalseKeyword) {
19078
+ return unreachableNeverType;
19079
+ }
19052
19080
if (node.kind === SyntaxKind.BinaryExpression) {
19053
19081
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
19054
19082
return narrowTypeByAssertion(narrowTypeByAssertion(type, (<BinaryExpression>node).left), (<BinaryExpression>node).right);
@@ -19068,7 +19096,7 @@ namespace ts {
19068
19096
const flowType = getTypeAtFlowNode(flow.antecedent);
19069
19097
const type = getTypeFromFlowType(flowType);
19070
19098
const narrowedType = predicate.type ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) :
19071
- predicate.kind === TypePredicateKind.AssertsIdentifier ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) :
19099
+ predicate.kind === TypePredicateKind.AssertsIdentifier && predicate.parameterIndex < flow.node.arguments.length ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) :
19072
19100
type;
19073
19101
return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
19074
19102
}
0 commit comments