@@ -19187,13 +19187,18 @@ namespace ts {
1918719187 type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
1918819188 }
1918919189 else {
19190- if (strictNullChecks && optionalChainContainsReference(expr, reference)) {
19191- type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
19190+ if (strictNullChecks) {
19191+ if (optionalChainContainsReference(expr, reference)) {
19192+ type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
19193+ t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never)));
19194+ }
19195+ else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) {
19196+ type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
19197+ t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (<StringLiteralType>t).value === "undefined"));
19198+ }
1919219199 }
1919319200 if (isMatchingReferenceDiscriminant(expr, type)) {
19194- type = narrowTypeByDiscriminant(
19195- type,
19196- expr as AccessExpression,
19201+ type = narrowTypeByDiscriminant(type, expr as AccessExpression,
1919719202 t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
1919819203 }
1919919204 else if (containsMatchingReferenceDiscriminant(reference, expr)) {
@@ -19539,10 +19544,9 @@ namespace ts {
1953919544 }
1954019545 }
1954119546
19542- function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
19543- const noClauseIsDefaultOrUndefined = clauseStart !== clauseEnd &&
19544- every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never)));
19545- return noClauseIsDefaultOrUndefined ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
19547+ function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) {
19548+ const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck);
19549+ return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
1954619550 }
1954719551
1954819552 function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
@@ -19771,8 +19775,9 @@ namespace ts {
1977119775 if (isMatchingReference(reference, predicateArgument)) {
1977219776 return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
1977319777 }
19774- if (strictNullChecks && assumeTrue && !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) {
19775- type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
19778+ if (strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) &&
19779+ !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) {
19780+ return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
1977619781 }
1977719782 if (containsMatchingReference(reference, predicateArgument)) {
1977819783 return declaredType;
0 commit comments