Typescript: Using the switched variable in an if statement causes an error.

Created on 20 Oct 2018  路  5Comments  路  Source: microsoft/TypeScript

TypeScript Version: 3.1

Search Terms: switch, if, switch this

Code

class MyClass{
  myString: string;

  setString() {
    this.myString = "c";
  }

  doSomeSwitching() {
    switch (this.myString) {
      case "a":
        this.setString();
        if (this.myString == "c") {

        }
        break;
      default:
        break;
    }
  }
}

Expected behavior:
I would expect no error.

Actual behavior:
An error is generated for the if statement.

if (this.myString == "c")
This condition will always return 'false' since the types '"a"' and '"c"' have no overlap.

The code above is the simplest form. In real use I was creating a parser. Using an instance variable to step through tokens. I check the token type with the case and then "eat" the token. The instance variable is then changed after which I want to check the token again.

Playground Link:
Link

Related Issues: I couldn't find anything that looked like this. Honestly I was mostly looking at the examples they gave since I'm not sure what many of the big words mean.

Design Limitation

Most helpful comment

This is a design limitation. See discussion in #9998.

All 5 comments

Interesting problem 馃 I changed it so it would work but solution is not the best, but should be fine. You need to write to myString directly instead of writing to it in method, well you can but need to write it in the "case" so it won't show that error.

class MyClass{
  myString: string;

  setString(new_s) {
    this.myString = new_s;
    return this.myString // <---  added this line
  }

  doSomeSwitching() {
    switch (this.myString) {
      case "a": {
        this.myString = this.setString("c") // <-- solution to this problem is to modify 
        // myString directly so TypeScript know's that it was changed to different value
        if (this.myString == "c")
        {

        }

        break;
      }

      default: {
        // ok
      }
    }
    }
  }
}

Nice, I didn't think of doing that. I found that any assignment will make it happy. So you don't even have to mess with the function.

class MyClass{
  myString: string;

  setString() {
    this.myString = "c";
  }

  doSomeSwitching() {
    switch (this.myString) {
      case "a":
        this.setString();
        this.myString = this.myString; // <-- Adding this takes the error away.
        if (this.myString == "c") {

        }
        break;
      default:
        break;
    }
  }
}

This is a design limitation. See discussion in #9998.

Is there any real-world benefit to the type being narrowed to a literal inside the cases?

this.myString = this.myString;

Why does this work to widen the type? In the example given, TS thinks the type of myString is "a" at that point, so assigning it to itself causing it to be widened seems counterintuitive.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Gaelan picture Gaelan  路  231Comments

fdecampredon picture fdecampredon  路  358Comments

tenry92 picture tenry92  路  146Comments

sandersn picture sandersn  路  265Comments

rbuckton picture rbuckton  路  139Comments