@@ -15441,6 +15441,32 @@ namespace ts {
1544115441                return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]);
1544215442            }
1544315443
15444+             function getImpliedTypeFromTypeofCase(type: Type, text: string) {
15445+                 switch (text) {
15446+                     case "function":
15447+                         return type.flags & TypeFlags.Any ? type : globalFunctionType;
15448+                     case "object":
15449+                         return type.flags & TypeFlags.Unknown ? getUnionType([nonPrimitiveType, nullType]) : type;
15450+                     default:
15451+                         return typeofTypesByName.get(text) || type;
15452+                 }
15453+             }
15454+ 
15455+             function narrowTypeForTypeofSwitch(candidate: Type) {
15456+                 return (type: Type) => {
15457+                     if (isTypeSubtypeOf(candidate, type)) {
15458+                         return candidate;
15459+                     }
15460+                     if (type.flags & TypeFlags.Instantiable) {
15461+                         const constraint = getBaseConstraintOfType(type) || anyType;
15462+                         if (isTypeSubtypeOf(candidate, constraint)) {
15463+                             return getIntersectionType([type, candidate]);
15464+                         }
15465+                     }
15466+                     return type;
15467+                 };
15468+             }
15469+ 
1544415470            function narrowBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type {
1544515471                const switchWitnesses = getSwitchClauseTypeOfWitnesses(switchStatement);
1544615472                if (!switchWitnesses.length) {
@@ -15458,7 +15484,7 @@ namespace ts {
1545815484                    // that we don't have to worry about undefined
1545915485                    // in the witness array.
1546015486                    const witnesses = <string[]>switchWitnesses.filter(witness => witness !== undefined);
15461-                     // The adjust  clause start and end after removing the `default` statement.
15487+                     // The adjusted  clause start and end after removing the `default` statement.
1546215488                    const fixedClauseStart = defaultCaseLocation < clauseStart ? clauseStart - 1 : clauseStart;
1546315489                    const fixedClauseEnd = defaultCaseLocation < clauseEnd ? clauseEnd - 1 : clauseEnd;
1546415490                    clauseWitnesses = witnesses.slice(fixedClauseStart, fixedClauseEnd);
@@ -15468,6 +15494,9 @@ namespace ts {
1546815494                    clauseWitnesses = <string[]>switchWitnesses.slice(clauseStart, clauseEnd);
1546915495                    switchFacts = getFactsFromTypeofSwitch(clauseStart, clauseEnd, <string[]>switchWitnesses, hasDefaultClause);
1547015496                }
15497+                 if (hasDefaultClause) {
15498+                     return filterType(type, t => (getTypeFacts(t) & switchFacts) === switchFacts);
15499+                 }
1547115500                /*
1547215501                  The implied type is the raw type suggested by a
1547315502                  value being caught in this clause.
@@ -15496,26 +15525,11 @@ namespace ts {
1549615525                  boolean. We know that number cannot be selected
1549715526                  because it is caught in the first clause.
1549815527                */
15499-                 if (!(hasDefaultClause || (type.flags & TypeFlags.Union))) {
15500-                     let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => typeofTypesByName.get(text) || neverType)), switchFacts);
15501-                     if (impliedType.flags & TypeFlags.Union) {
15502-                         impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOfType(type) || type);
15503-                     }
15504-                     if (!(impliedType.flags & TypeFlags.Never)) {
15505-                         if (isTypeSubtypeOf(impliedType, type)) {
15506-                             return impliedType;
15507-                         }
15508-                         if (type.flags & TypeFlags.Instantiable) {
15509-                             const constraint = getBaseConstraintOfType(type) || anyType;
15510-                             if (isTypeSubtypeOf(impliedType, constraint)) {
15511-                                 return getIntersectionType([type, impliedType]);
15512-                             }
15513-                         }
15514-                     }
15528+                 let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => getImpliedTypeFromTypeofCase(type, text))), switchFacts);
15529+                 if (impliedType.flags & TypeFlags.Union) {
15530+                     impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOrType(type));
1551515531                }
15516-                 return hasDefaultClause ?
15517-                     filterType(type, t => (getTypeFacts(t) & switchFacts) === switchFacts) :
15518-                     getTypeWithFacts(type, switchFacts);
15532+                 return getTypeWithFacts(mapType(type, narrowTypeForTypeofSwitch(impliedType)), switchFacts);
1551915533            }
1552015534
1552115535            function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
0 commit comments