Skip to content

Commit f7b22a0

Browse files
committed
Support typeof and instanceof
1 parent 464d1a7 commit f7b22a0

File tree

2 files changed

+13
-5
lines changed

2 files changed

+13
-5
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -856,9 +856,8 @@ namespace ts {
856856
function isNarrowableReference(expr: Expression): boolean {
857857
return expr.kind === SyntaxKind.Identifier || expr.kind === SyntaxKind.ThisKeyword || expr.kind === SyntaxKind.SuperKeyword ||
858858
(isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) ||
859-
isElementAccessExpression(expr) &&
860-
isStringOrNumericLiteralLike(expr.argumentExpression) &&
861-
isNarrowableReference(expr.expression);
859+
isElementAccessExpression(expr) && isStringOrNumericLiteralLike(expr.argumentExpression) && isNarrowableReference(expr.expression) ||
860+
isOptionalChain(expr);
862861
}
863862

864863
function hasNarrowableArgument(expr: CallExpression) {

src/compiler/checker.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19360,7 +19360,7 @@ namespace ts {
1936019360
if (isMatchingReference(reference, right)) {
1936119361
return narrowTypeByEquality(type, operator, left, assumeTrue);
1936219362
}
19363-
if (assumeTrue && (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) {
19363+
if (assumeTrue && strictNullChecks) {
1936419364
if (optionalChainContainsReference(left, reference)) {
1936519365
type = narrowTypeByOptionalChainContainment(type, operator, right);
1936619366
}
@@ -19397,7 +19397,9 @@ namespace ts {
1939719397
// the type of obj if (a) the operator is === and the type of value doesn't include undefined or (b) the
1939819398
// operator is !== and the type of value is undefined.
1939919399
const valueType = getTypeOfExpression(value);
19400-
return operator === SyntaxKind.EqualsEqualsEqualsToken && !(getTypeFacts(valueType) & TypeFacts.EQUndefined) ||
19400+
return operator === SyntaxKind.EqualsEqualsToken && !(getTypeFacts(valueType) & TypeFacts.EQUndefinedOrNull) ||
19401+
operator === SyntaxKind.EqualsEqualsEqualsToken && !(getTypeFacts(valueType) & TypeFacts.EQUndefined) ||
19402+
operator === SyntaxKind.ExclamationEqualsToken && valueType.flags & TypeFlags.Nullable ||
1940119403
operator === SyntaxKind.ExclamationEqualsEqualsToken && valueType.flags & TypeFlags.Undefined ?
1940219404
getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
1940319405
}
@@ -19452,6 +19454,10 @@ namespace ts {
1945219454
// We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands
1945319455
const target = getReferenceCandidate(typeOfExpr.expression);
1945419456
if (!isMatchingReference(reference, target)) {
19457+
if (assumeTrue && (operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken) &&
19458+
strictNullChecks && optionalChainContainsReference(target, reference)) {
19459+
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
19460+
}
1945519461
// For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the
1945619462
// narrowed type of 'y' to its declared type.
1945719463
if (containsMatchingReference(reference, target)) {
@@ -19633,6 +19639,9 @@ namespace ts {
1963319639
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
1963419640
const left = getReferenceCandidate(expr.left);
1963519641
if (!isMatchingReference(reference, left)) {
19642+
if (assumeTrue && strictNullChecks && optionalChainContainsReference(left, reference)) {
19643+
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
19644+
}
1963619645
// For a reference of the form 'x.y', an 'x instanceof T' type guard resets the
1963719646
// narrowed type of 'y' to its declared type. We do this because preceding 'x.y'
1963819647
// references might reference a different 'y' property. However, we make an exception

0 commit comments

Comments
 (0)