@@ -16864,6 +16864,44 @@ namespace ts {
1686416864 return false;
1686516865 }
1686616866
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+
1686716905 function reportFlowControlError(node: Node) {
1686816906 const block = <Block | ModuleBlock | SourceFile>findAncestor(node, isFunctionOrModuleBlock);
1686916907 const sourceFile = getSourceFileOfNode(node);
@@ -16962,6 +17000,13 @@ namespace ts {
1696217000 }
1696317001 }
1696417002 }
17003+ else if (flags & FlowFlags.Call) {
17004+ type = getTypeAtFlowCall(<FlowCall>flow);
17005+ if (!type) {
17006+ flow = (<FlowCall>flow).antecedent;
17007+ continue;
17008+ }
17009+ }
1696517010 else if (flags & FlowFlags.Condition) {
1696617011 type = getTypeAtFlowCondition(<FlowCondition>flow);
1696717012 }
@@ -17057,6 +17102,32 @@ namespace ts {
1705717102 return undefined;
1705817103 }
1705917104
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+
1706017131 function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined {
1706117132 if (declaredType === autoType || declaredType === autoArrayType) {
1706217133 const node = flow.node;
0 commit comments