Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"This condition will always return 'false'" but returns true at runtime #26592

Closed
ghost opened this issue Aug 22, 2018 · 24 comments · Fixed by #50471
Closed

"This condition will always return 'false'" but returns true at runtime #26592

ghost opened this issue Aug 22, 2018 · 24 comments · Fixed by #50471
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging
Milestone

Comments

@ghost
Copy link

ghost commented Aug 22, 2018

TypeScript Version: 3.1.0-dev.20180818

Code

function sanityCheck(s: string): string {
	return s == 0 ? "I must be going insane" : "I'm fine";
}
console.log(sanityCheck(""));

Expected behavior:

Error message is 100% accurate.

Actual behavior:

src/a.ts:2:9 - error TS2367: This condition will always return 'false' since the types 'string' and 'number' have no overlap.

The == operator in JavaScript converts its arguments -- some developers apparently rely on this behavior (not naming names but I noticed this in real JavaScript code that I pasted into a TypeScript file).
The error message might recommend using an explicit conversion such as Number(s) to get this to compile in TypeScript.

CC @DanielRosenwasser

@ghost ghost added Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging labels Aug 22, 2018
@DanielRosenwasser
Copy link
Member

Yeah, we discussed == and != making the statement technically incorrect and decided to wait for the first bug report before addressing it.

@DanielRosenwasser DanielRosenwasser added this to the TypeScript 3.2 milestone Aug 22, 2018
@DanielRosenwasser DanielRosenwasser added Help Wanted You can do this Good First Issue Well scoped, documented and has the green light labels Aug 22, 2018
@DanielRosenwasser
Copy link
Member

I think just using the old error message is probably fine.

@Kingwl
Copy link
Contributor

Kingwl commented Aug 22, 2018

related #24991

@HZooly
Copy link

HZooly commented Aug 27, 2018

I got this error Operator '==' cannot be applied to types 'string' and 'number'. in Stackblitz.
https://stackblitz.com/edit/typescript-vwakj2

EDIT : Sorry, Typescript current version on Stackblitz shouldn't be 3.1.x

@ghost
Copy link
Author

ghost commented Aug 27, 2018

@HZooly That links to a document that doesn't use == anywhere?
Regardless, the solution is probably to be more explicit, and convert the string to Number(s) or the number to String(n), then use ===.

@HZooly
Copy link

HZooly commented Aug 28, 2018

@andy-ms Sorry my snippet wasn't saved! Now it has been updated :)

@ghost ghost added the Fixed A PR has been merged for this issue label Sep 19, 2018
@JohnPool
Copy link

I get the same error message for the following code:

image

image

@ghost
Copy link
Author

ghost commented Oct 22, 2018

@JohnPool See #9998

@JohnPool
Copy link

Thank you for pointing me to this interesting discussion!

@ConnorsFan
Copy link

ConnorsFan commented Nov 6, 2018

I get this very annoying bug even with === in the following code snippet (see this stackblitz). The variable is set to an enum value and modified in a callback:

enum MyEnum {
  Value1,
  Value2,
  Value3
}

export class AppComponent {

  constructor() {
    this.doProcess();
  }

  doProcess() {
    let value: MyEnum;
    value = MyEnum.Value1;

    [1, 2, 3].forEach(x => {
      if (x > 1) {
        value = MyEnum.Value2;
      }
    });

    // The following condition evaluates to 'true'
    // but it is underlined in red with "This condition will always return 'false'..."
    if (value === MyEnum.Value2) {
      console.log("Hello world");
    }
  }
}

@ghost
Copy link
Author

ghost commented Nov 6, 2018

@ConnorsFan See #9998

@ConnorsFan
Copy link

@andy-ms The error goes away when I initialize the value as a number. I don't know if that is a recommended workaround:

let value = +MyEnum.Value1;

@ghost
Copy link
Author

ghost commented Nov 6, 2018

May be better to write MyEnum.Value1 as MyEnum because that at least specifies it as MyEnum rather than number.

@ConnorsFan
Copy link

ConnorsFan commented Nov 6, 2018

@andy-ms I don't understand your last comment. Maybe I should add that the bug is also present if I do this:

let value: MyEnum;
value = MyEnum.Value1;

In other words, I don't know how to make the code work when value is of type MyEnum.

@ghost
Copy link
Author

ghost commented Nov 6, 2018

If you write +MyEnum.Value1 it's a number and could be passed to a function expecting a different enum. If you write MyEnum.Value1 as MyEnum it stays MyEnum and can't be used as an instance of a different enum.

@ConnorsFan
Copy link

OK, it works. Sorry, I had misread you previous comment. I didn't think that you meant as MyEnum literally in code.

@ghost ghost removed Help Wanted You can do this Good First Issue Well scoped, documented and has the green light labels Nov 16, 2018
@ghost ghost assigned DanielRosenwasser and unassigned ghost Nov 16, 2018
@vigneshTheDev
Copy link

vigneshTheDev commented Jan 1, 2020

I have a similar scenario. Here is the minimal reproduction:

enum types {
  type1 = 'type1',
  type2 = 'type2'
}

class A {
  private h: types = types.type1;
  
  private a() {
    this.h = types.type2;

    this.b();
    // Actual error here: the method b changes h to types.type1. But typescript thinks this.h would always be types.type2.
    if (this.h === types.type1) { // This condition will always return 'false' since the types 'types.type2' and 'types.type1' have no overlap.

      console.log('hello')
    }
  }

  private b() {
    this.h = types.type1;
  }
}

See it live here: https://stackblitz.com/edit/typescript-qvs8ov

@shalomhalbert
Copy link

Is this not getting fixed?

@SrBrahma
Copy link

SrBrahma commented Nov 21, 2020

I started to use @typescript-eslint/strict-boolean-expressions after I found a silly mistake in my code that could have costed me a lot of money, as I did a numberOrUndefinedVar ? X : Y, and 0 was not intentionally falling into Y, and it was making hundreds of DB calls.

This rule is very good, but, doesn't work very good with TS due to a current fact: If you want to check a falsy value (e.g. empty string and undefined), with == false, TS will throw This condition will always return 'false' since the types 'string | undefined' and 'boolean' have no overlap.ts(2367).

I have made, before this == false idea, a question in Stackoverflow about it, how to check for falsy value using this rule. While the two current answers are valid, they really aren't good to use outside your own code, where you know why you are using it and won't need to comment why you did those strange workarounds.

So, == false should be TS friendly, as it works as expected in JS.

Current TS version: 4.1.2

@TomasSestak
Copy link

are we getting fix?

@wbt
Copy link

wbt commented Mar 11, 2022

Can someone point more specifically to where this error-check happens, to facilitate a PR that disables the check for == and != cases? I'm not able to find it, even in code search.
To see that this bug has been known for years with an intentional decision to just not fix it until there were a sufficiently large number of errors - and then it not being fixed after that threshold was exceeded - really communicates that TypeScript isn't ready for prime-time use or production code yet.

@BlackAsLight
Copy link

BlackAsLight commented Aug 22, 2022

It really annoys me that this has been a bug for years and looks like the devs here have no interest in resolving it. Not only is the error message misleading and wrong, TypeScript is failing to be a superset of JavaScript as it's not allowing me to do perfectly valid JavaScript.

Frankly whether anyone considers it to be bad practice to allow an implicit conversion or not is irrelevant. We who are developing our own code should be allowed to make that choice for ourselves. I as the developer should be able to choose what parts of the language I use to the fullest.

@RyanCavanaugh
Copy link
Member

TypeScript is failing to be a superset of JavaScript as it's not allowing me to do perfectly valid JavaScript.

It has never been the case that no JS you could possibly write would issue zero errors in TypeScript, nor would this make any sense. See https://stackoverflow.com/questions/41750390/what-does-all-legal-javascript-is-legal-typescript-mean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging
Projects
None yet