(type, switchStatement, clauseStart, clauseEnd)
| 71135 | }; |
| 71136 | } |
| 71137 | function narrowBySwitchOnTypeOf(type, switchStatement, clauseStart, clauseEnd) { |
| 71138 | var switchWitnesses = getSwitchClauseTypeOfWitnesses(switchStatement, /*retainDefault*/ true); |
| 71139 | if (!switchWitnesses.length) { |
| 71140 | return type; |
| 71141 | } |
| 71142 | // Equal start and end denotes implicit fallthrough; undefined marks explicit default clause |
| 71143 | var defaultCaseLocation = ts.findIndex(switchWitnesses, function (elem) { return elem === undefined; }); |
| 71144 | var hasDefaultClause = clauseStart === clauseEnd || (defaultCaseLocation >= clauseStart && defaultCaseLocation < clauseEnd); |
| 71145 | var clauseWitnesses; |
| 71146 | var switchFacts; |
| 71147 | if (defaultCaseLocation > -1) { |
| 71148 | // We no longer need the undefined denoting an explicit default case. Remove the undefined and |
| 71149 | // fix-up clauseStart and clauseEnd. This means that we don't have to worry about undefined in the |
| 71150 | // witness array. |
| 71151 | var witnesses = switchWitnesses.filter(function (witness) { return witness !== undefined; }); |
| 71152 | // The adjusted clause start and end after removing the `default` statement. |
| 71153 | var fixedClauseStart = defaultCaseLocation < clauseStart ? clauseStart - 1 : clauseStart; |
| 71154 | var fixedClauseEnd = defaultCaseLocation < clauseEnd ? clauseEnd - 1 : clauseEnd; |
| 71155 | clauseWitnesses = witnesses.slice(fixedClauseStart, fixedClauseEnd); |
| 71156 | switchFacts = getFactsFromTypeofSwitch(fixedClauseStart, fixedClauseEnd, witnesses, hasDefaultClause); |
| 71157 | } |
| 71158 | else { |
| 71159 | clauseWitnesses = switchWitnesses.slice(clauseStart, clauseEnd); |
| 71160 | switchFacts = getFactsFromTypeofSwitch(clauseStart, clauseEnd, switchWitnesses, hasDefaultClause); |
| 71161 | } |
| 71162 | if (hasDefaultClause) { |
| 71163 | return filterType(type, function (t) { return (getTypeFacts(t) & switchFacts) === switchFacts; }); |
| 71164 | } |
| 71165 | /* |
| 71166 | The implied type is the raw type suggested by a |
| 71167 | value being caught in this clause. |
| 71168 | |
| 71169 | When the clause contains a default case we ignore |
| 71170 | the implied type and try to narrow using any facts |
| 71171 | we can learn: see `switchFacts`. |
| 71172 | |
| 71173 | Example: |
| 71174 | switch (typeof x) { |
| 71175 | case 'number': |
| 71176 | case 'string': break; |
| 71177 | default: break; |
| 71178 | case 'number': |
| 71179 | case 'boolean': break |
| 71180 | } |
| 71181 | |
| 71182 | In the first clause (case `number` and `string`) the |
| 71183 | implied type is number | string. |
| 71184 | |
| 71185 | In the default clause we de not compute an implied type. |
| 71186 | |
| 71187 | In the third clause (case `number` and `boolean`) |
| 71188 | the naive implied type is number | boolean, however |
| 71189 | we use the type facts to narrow the implied type to |
| 71190 | boolean. We know that number cannot be selected |
| 71191 | because it is caught in the first clause. |
| 71192 | */ |
| 71193 | var impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(function (text) { return getImpliedTypeFromTypeofGuard(type, text) || type; })), switchFacts); |
| 71194 | return getTypeWithFacts(mapType(type, narrowUnionMemberByTypeof(impliedType)), switchFacts); |
no test coverage detected
searching dependent graphs…