Skip to content

This condition will always return 'false' since the types have no overlap. #25642

Closed

Description

TypeScript Version: 3.0.0-dev.20180712
Error: This condition will always return 'false' since the types 'A' and 'I' have no overlap.
TypeScript Version: 2.9.2
Error: Operator '===' cannot be applied to types 'A' and 'I'

Search Terms:
Operator '===' cannot be applied to types
This condition will always return 'false' since the types have no overlap.
Code

class A { 
  private field: string;
}
interface I { 
  pub: string;
}
class B extends A implements I { 
  pub: string;
}
let b = new B();
let a: A = b
let i: I = b;
if (a === i) { // on TS 2.9.2: Operator '===' cannot be applied to types 'A' and 'I'
// on TS 3.0.0-dev.20180712:  This condition will always return 'false' since the types 'A' and 'I' have no overlap.
  console.log('qq');
}

Expected behavior:
no error
Actual behavior:
error
Playground Link: link

Related Issues: no

This case found from real project. Class and interface may be implemented and extended by another class, and in this case this error is pointless.

Activity

  1. changed the title [-]This condition will always return 'false' since the types 'A' and 'I' have no overlap.[/-] [+]This condition will always return 'false' since the types have no overlap.[/+] on Jul 13, 2018
  2. Busyrev commented on Jul 13, 2018

    @Busyrev
    ContributorAuthor

    Another case for classes without interfaces

    class A { 
      private field: string;
    }
    class B { 
      public anotherField: string;
    }
    class C extends A implements B { 
      public anotherField: string;
    }
    let c = new C();
    let a: A = c
    let b: B = c;
    if (a === b) { // on TS 2.9.2: Operator '===' cannot be applied to types 'A' and 'B'
    // on TS 3.0.0-dev.20180712:  This condition will always return 'false' since the types 'A' and 'B' have no overlap.
      console.log('qq');
    }
    

    Playground

  3. mhegazy commented on Jul 13, 2018

    @mhegazy
    Contributor
  4. mhegazy commented on Jul 13, 2018

    @mhegazy
    Contributor

    The rule for the type assertion is that the compiler can verify that either of the two types is comparable to the other. In simpler terms, can you assign one to the other either upcast or downcast. if neither is true, then it is likely an error.. e.g. 3 === "string".

  5. AnyhowStep commented on Jul 13, 2018

    @AnyhowStep
    Contributor

    On one hand, it looks like a code smell to compare types like this.

    On the other, if such a check passes, I would expect it to behave like some sort of type guard, where both a and i are now of type A & I or something to that effect.

  6. Busyrev commented on Jul 13, 2018

    @Busyrev
    ContributorAuthor

    In simple cases yes, looks good. But in some cases it alerts on absolutely correct code. Found this case in complicated code that works with heirechical system using abstract interfaces. All parent - child links is interfaces, and nodes implemets this interfaces.
    Think thak this error should be emitted if both arguments primitive or nominal types only. If type of one side is not nominal, its incorrect to prevent equality check.
    To be more clear. I think that its design issue.
    No error in С# but there is error comparing int and string

  7. RyanCavanaugh commented on Jul 13, 2018

    @RyanCavanaugh
    Member

    The current rule covers a large class of errors with good precision; it will necessarily have some false positives but we have carefully considered this and are satisfied with the current balance of value vs "incorrect" errors.

  8. vovkasm commented on Jul 16, 2018

    @vovkasm

    Ryan Cavanaugh (@RyanCavanaugh) And how do you propose to correct these "incorrect" errors? What developers should do?

  9. Busyrev commented on Jul 16, 2018

    @Busyrev
    ContributorAuthor
  10. AM-young-fun commented on Dec 5, 2018

    @AM-young-fun

    image

    How you guys solve this?

  11. AnyhowStep commented on Dec 5, 2018

    @AnyhowStep
    Contributor

    @AntiMoron
    Shouldn't it be process.env.<someIdentifier> == 'development'?

    [EDIT]

    If env is also your identifier, then, process.env.env == 'development'

  12. AM-young-fun commented on Dec 6, 2018

    @AM-young-fun

    AnyhowStep Thank you...I redefined process.env as a string...
    Seems to be my problem.

  13. AnyhowStep commented on Dec 6, 2018

    @AnyhowStep
    Contributor

    @AntiMoron How did you even get that to work? o.0

    process.env is supposed to be an object, not a string.

    https://nodejs.org/api/process.html#process_process_env


    Are you using process outside of node? Are you somehow overwriting process.env in code elsewhere?

  14. 14 remaining items

  15. kevincox commented on Feb 20, 2020

    @kevincox

    This is a very poorly worded "error". For example the following code: "1" == 1 triggered the error. While the error claims "This condition will always return 'false'" it in fact evaluates to true. This is incredibly misleading.

    Playground Link

  16. BertCatsburg commented on Feb 24, 2020

    @BertCatsburg

    I got the same error-message with the following code:

    let x = null;
    if ( some-condition ) {
      x = 0;
    } else {
      x = 1;
    }
    if ( x === 0 ) {
      // Do something
    }
    

    On the x===0 condition I got the error, which was strange in my view because I was sure the x is either 0 or 1.
    But the culprit was the initialization to null.
    Changed that to:

    let x;
    

    And it solved the problem.
    If it's a casting problem then its still strange because the program has x casted to an int the moment of the first condition. (x = 0 or x = 1)

  17. victor-zy commented on Jun 16, 2020

    @victor-zy

    typeof a === b,试一下咯

  18. dougmotshell commented on Jul 16, 2020

    @dougmotshell

    I solved this situation
    image

    using String()
    image

  19. snarfblam commented on Jul 21, 2020

    @snarfblam

    I solved this situation

    This is just another example of someone introducing a bug into their program to try to fix this error message. There is generally no good reason to use String, and now you have a function that is supposed to return a boolean that is instead returning String('true') or String('false'), both of which are objects, thus truthy.

    Ryan Cavanaugh (@RyanCavanaugh) Is there any chance we can re-open this issue to consider re-wording the error message? I think it should convey:

    • That the comparison is probably erroneous
    • That the comparison may also merely require a cast to help unconfuse the compiler.

    Perhaps something along the lines of:

    This condition may always return 'false' since the declared types have no overlap. Consider casting if the compared values are known to be of compatible types.

  20. Aloso commented on Oct 9, 2020

    @Aloso

    @NeliHarbuzava Your code is wrong, it currently always returns true, even if imageFormat is "png" or "jpg". The correct code would be

    if (typeof imageFormat !== 'string' || (imageFormat !== 'png' && imageFormat !== 'jpg')) {
        //                                                        ^^ problem solved
        console.warn('Invalid "imageFormat" property. Expected one of: "png", "jpg".');
    }
  21. snarfblam commented on Oct 9, 2020

    @snarfblam

    This condition will always return 'true' since the types '"png"' and '"jpg"' have no overlap

    This demonstrates the actual utility of the error message. imageFormat !== 'png' || imageFormat !== 'jpg' will always return true, because it will always be inequal to at least one of the two ('jpg' or 'png'). It would be nice if TS could distinguish between genuine "will always return true" versus heuristic "may always return true", but I'd settle for any improvement to how the error is reported.

  22. OliverEvans96 commented on Nov 2, 2020

    @OliverEvans96

    Daniel Windham (@tenedor) - thanks for the succinct MWE - I'm in the same situation.

    const x = <T extends SomeType, U extends SomeType> (t: T, u: U) => {
        if (t === u) {
            ...
        } else {
            ...
        }
    }

    One simple workaround is to set u: T | U, although that may have unintended consequences I'm not aware of.

  23. galenwinsor commented on Jul 19, 2022

    @galenwinsor

    As far as I can tell, this is still an issue. As Kevin Cox (@kevincox) points out, the simple expression '1' == 1 throws this error, which is extremely misleading. Ryan Cavanaugh (@RyanCavanaugh) can you clarify why the wording of the error is useful? (I.e., "will always return false" as opposed to "may return false"). Thank you!

  24. RyanCavanaugh commented on Jul 19, 2022

    @RyanCavanaugh
    Member

    See #26592

  25. galenwinsor commented on Jul 19, 2022

    @galenwinsor

    Ryan Cavanaugh (@RyanCavanaugh) I guess I don't see how that answers the question. I can see the use of pointing out the potential bug-iness of using ==, but the language of the error message is misleading and also incorrect, isn't it?

  26. RyanCavanaugh commented on Jul 19, 2022

    @RyanCavanaugh
    Member

    Yes, and the linked issue says that we'd love a PR to change the language of that error message.

  27. galenwinsor commented on Jul 19, 2022

    @galenwinsor

    Ahhh okay, sorry for the confusion. Thank you!

  28. galenwinsor commented on Jul 19, 2022

    @galenwinsor

    Ryan Cavanaugh (@RyanCavanaugh) could you point me to where this check happens in the code?

  29. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions