(flow)
| 70595 | return createFlowType(type, isIncomplete(flowType)); |
| 70596 | } |
| 70597 | function getTypeAtFlowBranchLabel(flow) { |
| 70598 | var antecedentTypes = []; |
| 70599 | var subtypeReduction = false; |
| 70600 | var seenIncomplete = false; |
| 70601 | var bypassFlow; |
| 70602 | for (var _i = 0, _a = flow.antecedents; _i < _a.length; _i++) { |
| 70603 | var antecedent = _a[_i]; |
| 70604 | if (!bypassFlow && antecedent.flags & 128 /* FlowFlags.SwitchClause */ && antecedent.clauseStart === antecedent.clauseEnd) { |
| 70605 | // The antecedent is the bypass branch of a potentially exhaustive switch statement. |
| 70606 | bypassFlow = antecedent; |
| 70607 | continue; |
| 70608 | } |
| 70609 | var flowType = getTypeAtFlowNode(antecedent); |
| 70610 | var type = getTypeFromFlowType(flowType); |
| 70611 | // If the type at a particular antecedent path is the declared type and the |
| 70612 | // reference is known to always be assigned (i.e. when declared and initial types |
| 70613 | // are the same), there is no reason to process more antecedents since the only |
| 70614 | // possible outcome is subtypes that will be removed in the final union type anyway. |
| 70615 | if (type === declaredType && declaredType === initialType) { |
| 70616 | return type; |
| 70617 | } |
| 70618 | ts.pushIfUnique(antecedentTypes, type); |
| 70619 | // If an antecedent type is not a subset of the declared type, we need to perform |
| 70620 | // subtype reduction. This happens when a "foreign" type is injected into the control |
| 70621 | // flow using the instanceof operator or a user defined type predicate. |
| 70622 | if (!isTypeSubsetOf(type, declaredType)) { |
| 70623 | subtypeReduction = true; |
| 70624 | } |
| 70625 | if (isIncomplete(flowType)) { |
| 70626 | seenIncomplete = true; |
| 70627 | } |
| 70628 | } |
| 70629 | if (bypassFlow) { |
| 70630 | var flowType = getTypeAtFlowNode(bypassFlow); |
| 70631 | var type = getTypeFromFlowType(flowType); |
| 70632 | // If the bypass flow contributes a type we haven't seen yet and the switch statement |
| 70633 | // isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase |
| 70634 | // the risk of circularities, we only want to perform them when they make a difference. |
| 70635 | if (!ts.contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) { |
| 70636 | if (type === declaredType && declaredType === initialType) { |
| 70637 | return type; |
| 70638 | } |
| 70639 | antecedentTypes.push(type); |
| 70640 | if (!isTypeSubsetOf(type, declaredType)) { |
| 70641 | subtypeReduction = true; |
| 70642 | } |
| 70643 | if (isIncomplete(flowType)) { |
| 70644 | seenIncomplete = true; |
| 70645 | } |
| 70646 | } |
| 70647 | } |
| 70648 | return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 /* UnionReduction.Subtype */ : 1 /* UnionReduction.Literal */), seenIncomplete); |
| 70649 | } |
| 70650 | function getTypeAtFlowLoopLabel(flow) { |
| 70651 | // If we have previously computed the control flow type for the reference at |
| 70652 | // this flow loop junction, return the cached type. |
no test coverage detected
searching dependent graphs…