@@ -16864,6 +16864,44 @@ namespace ts {
16864
16864
return false;
16865
16865
}
16866
16866
16867
+ function getTypeOfDottedName(node: Expression) {
16868
+ if (node.kind === SyntaxKind.Identifier) {
16869
+ const symbol = getResolvedSymbol(<Identifier>node);
16870
+ const nonAliasSymbol = symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol;
16871
+ return nonAliasSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.ValueModule) ? getTypeOfSymbol(nonAliasSymbol) : undefined;
16872
+ }
16873
+ if (node.kind === SyntaxKind.PropertyAccessExpression) {
16874
+ const type = getTypeOfDottedName((<PropertyAccessExpression>node).expression);
16875
+ if (type) {
16876
+ const prop = getPropertyOfType(type, (<PropertyAccessExpression>node).name.escapedText);
16877
+ return prop && prop.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule) ? getTypeOfSymbol(prop) : undefined;
16878
+ }
16879
+ }
16880
+ }
16881
+
16882
+ function getIsAssertCall(node: CallExpression) {
16883
+ const type = getTypeOfDottedName(node.expression);
16884
+ if (type) {
16885
+ const signature = getSingleCallSignature(type);
16886
+ if (signature && signature.declaration) {
16887
+ const typeNode = getEffectiveReturnTypeNode(signature.declaration);
16888
+ if (typeNode && typeNode.kind === SyntaxKind.UnionType) {
16889
+ const types = (<UnionTypeNode>typeNode).types;
16890
+ return types.length === 2 && types[0].kind === SyntaxKind.VoidKeyword && types[1].kind === SyntaxKind.NeverKeyword;
16891
+ }
16892
+ }
16893
+ }
16894
+ return false;
16895
+ }
16896
+
16897
+ function isAssertCall(node: CallExpression) {
16898
+ const links = getNodeLinks(node);
16899
+ if (links.isAssertCall === undefined) {
16900
+ links.isAssertCall = getIsAssertCall(node);
16901
+ }
16902
+ return links.isAssertCall;
16903
+ }
16904
+
16867
16905
function reportFlowControlError(node: Node) {
16868
16906
const block = <Block | ModuleBlock | SourceFile>findAncestor(node, isFunctionOrModuleBlock);
16869
16907
const sourceFile = getSourceFileOfNode(node);
@@ -16962,6 +17000,13 @@ namespace ts {
16962
17000
}
16963
17001
}
16964
17002
}
17003
+ else if (flags & FlowFlags.Call) {
17004
+ type = getTypeAtFlowCall(<FlowCall>flow);
17005
+ if (!type) {
17006
+ flow = (<FlowCall>flow).antecedent;
17007
+ continue;
17008
+ }
17009
+ }
16965
17010
else if (flags & FlowFlags.Condition) {
16966
17011
type = getTypeAtFlowCondition(<FlowCondition>flow);
16967
17012
}
@@ -17057,6 +17102,32 @@ namespace ts {
17057
17102
return undefined;
17058
17103
}
17059
17104
17105
+ function narrowTypeByAssertion(type: Type, expr: Expression): Type {
17106
+ const node = skipParentheses(expr);
17107
+ if (node.kind === SyntaxKind.BinaryExpression) {
17108
+ if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
17109
+ return narrowTypeByAssertion(narrowTypeByAssertion(type, (<BinaryExpression>node).left), (<BinaryExpression>node).right);
17110
+ }
17111
+ if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
17112
+ return getUnionType([narrowTypeByAssertion(type, (<BinaryExpression>node).left), narrowTypeByAssertion(type, (<BinaryExpression>node).right)]);
17113
+ }
17114
+ }
17115
+ return narrowType(type, node, /*assumeTrue*/ true);
17116
+ }
17117
+
17118
+ function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined {
17119
+ if (isAssertCall(flow.node)) {
17120
+ const flowType = getTypeAtFlowNode(flow.antecedent);
17121
+ const type = getTypeFromFlowType(flowType);
17122
+ const narrowedType = narrowTypeByAssertion(type, flow.node.arguments[0]);
17123
+ if (narrowedType === type) {
17124
+ return flowType;
17125
+ }
17126
+ return createFlowType(narrowedType, isIncomplete(flowType));
17127
+ }
17128
+ return undefined;
17129
+ }
17130
+
17060
17131
function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined {
17061
17132
if (declaredType === autoType || declaredType === autoArrayType) {
17062
17133
const node = flow.node;
0 commit comments