(f *FlowState, t *Type, expr *ast.BinaryExpression, assumeTrue bool)
| 467 | } |
| 468 | |
| 469 | func (c *Checker) narrowTypeByBinaryExpression(f *FlowState, t *Type, expr *ast.BinaryExpression, assumeTrue bool) *Type { |
| 470 | switch expr.OperatorToken.Kind { |
| 471 | case ast.KindEqualsToken, ast.KindBarBarEqualsToken, ast.KindAmpersandAmpersandEqualsToken, ast.KindQuestionQuestionEqualsToken: |
| 472 | return c.narrowTypeByTruthiness(f, c.narrowType(f, t, expr.Right, assumeTrue), expr.Left, assumeTrue) |
| 473 | case ast.KindEqualsEqualsToken, ast.KindExclamationEqualsToken, ast.KindEqualsEqualsEqualsToken, ast.KindExclamationEqualsEqualsToken: |
| 474 | operator := expr.OperatorToken.Kind |
| 475 | left := c.getReferenceCandidate(expr.Left) |
| 476 | right := c.getReferenceCandidate(expr.Right) |
| 477 | if left.Kind == ast.KindTypeOfExpression && ast.IsStringLiteralLike(right) { |
| 478 | return c.narrowTypeByTypeof(f, t, left.AsTypeOfExpression(), operator, right, assumeTrue) |
| 479 | } |
| 480 | if right.Kind == ast.KindTypeOfExpression && ast.IsStringLiteralLike(left) { |
| 481 | return c.narrowTypeByTypeof(f, t, right.AsTypeOfExpression(), operator, left, assumeTrue) |
| 482 | } |
| 483 | if c.isMatchingReference(f.reference, left) { |
| 484 | return c.narrowTypeByEquality(t, operator, right, assumeTrue) |
| 485 | } |
| 486 | if c.isMatchingReference(f.reference, right) { |
| 487 | return c.narrowTypeByEquality(t, operator, left, assumeTrue) |
| 488 | } |
| 489 | if c.strictNullChecks { |
| 490 | if c.optionalChainContainsReference(left, f.reference) { |
| 491 | t = c.narrowTypeByOptionalChainContainment(f, t, operator, right, assumeTrue) |
| 492 | } else if c.optionalChainContainsReference(right, f.reference) { |
| 493 | t = c.narrowTypeByOptionalChainContainment(f, t, operator, left, assumeTrue) |
| 494 | } |
| 495 | } |
| 496 | leftAccess := c.getDiscriminantPropertyAccess(f, left, t) |
| 497 | if leftAccess != nil { |
| 498 | return c.narrowTypeByDiscriminantProperty(t, leftAccess, operator, right, assumeTrue) |
| 499 | } |
| 500 | rightAccess := c.getDiscriminantPropertyAccess(f, right, t) |
| 501 | if rightAccess != nil { |
| 502 | return c.narrowTypeByDiscriminantProperty(t, rightAccess, operator, left, assumeTrue) |
| 503 | } |
| 504 | if c.isMatchingConstructorReference(f, left) { |
| 505 | return c.narrowTypeByConstructor(t, operator, right, assumeTrue) |
| 506 | } |
| 507 | if c.isMatchingConstructorReference(f, right) { |
| 508 | return c.narrowTypeByConstructor(t, operator, left, assumeTrue) |
| 509 | } |
| 510 | if ast.IsBooleanLiteral(right) && !ast.IsAccessExpression(left) { |
| 511 | return c.narrowTypeByBooleanComparison(f, t, left, right, operator, assumeTrue) |
| 512 | } |
| 513 | if ast.IsBooleanLiteral(left) && !ast.IsAccessExpression(right) { |
| 514 | return c.narrowTypeByBooleanComparison(f, t, right, left, operator, assumeTrue) |
| 515 | } |
| 516 | case ast.KindInstanceOfKeyword: |
| 517 | return c.narrowTypeByInstanceof(f, t, expr, assumeTrue) |
| 518 | case ast.KindInKeyword: |
| 519 | if ast.IsPrivateIdentifier(expr.Left) { |
| 520 | return c.narrowTypeByPrivateIdentifierInInExpression(f, t, expr, assumeTrue) |
| 521 | } |
| 522 | target := c.getReferenceCandidate(expr.Right) |
| 523 | if c.containsMissingType(t) && ast.IsAccessExpression(f.reference) && c.isMatchingReference(f.reference.Expression(), target) { |
| 524 | leftType := c.getTypeOfExpression(expr.Left) |
| 525 | if isTypeUsableAsPropertyName(leftType) { |
| 526 | if accessedName, ok := c.getAccessedPropertyName(f.reference); ok && accessedName == getPropertyNameFromType(leftType) { |
no test coverage detected