@@ -19187,13 +19187,18 @@ namespace ts {
19187
19187
type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
19188
19188
}
19189
19189
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
+ }
19192
19199
}
19193
19200
if (isMatchingReferenceDiscriminant(expr, type)) {
19194
- type = narrowTypeByDiscriminant(
19195
- type,
19196
- expr as AccessExpression,
19201
+ type = narrowTypeByDiscriminant(type, expr as AccessExpression,
19197
19202
t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
19198
19203
}
19199
19204
else if (containsMatchingReferenceDiscriminant(reference, expr)) {
@@ -19539,10 +19544,9 @@ namespace ts {
19539
19544
}
19540
19545
}
19541
19546
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;
19546
19550
}
19547
19551
19548
19552
function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
@@ -19771,8 +19775,9 @@ namespace ts {
19771
19775
if (isMatchingReference(reference, predicateArgument)) {
19772
19776
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
19773
19777
}
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);
19776
19781
}
19777
19782
if (containsMatchingReference(reference, predicateArgument)) {
19778
19783
return declaredType;
0 commit comments