Skip to content

TS2454 after assigning a value from an exhaustive switch statement #18362

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

Closed
Firehed opened this issue Sep 9, 2017 · 4 comments · Fixed by #32695
Closed

TS2454 after assigning a value from an exhaustive switch statement #18362

Firehed opened this issue Sep 9, 2017 · 4 comments · Fixed by #32695
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue

Comments

@Firehed
Copy link

Firehed commented Sep 9, 2017

TypeScript Version: 2.4.2

Code

enum Level {
  One,
  Two,
}

const doSomethingWithLevel = (level: Level) => {
  let next: Level;
  switch (level) {
    case Level.One:
      next = Level.Two;
      break;
    case Level.Two:
      next = Level.One;
      break;
  }
  return next; // <-- Error here
};

Expected behavior:
Since the switch statement is exhaustive over the enum, the compiler should correctly infer that next is always set and this works without error.

Actual behavior:
(16,10): error TS2454: Variable 'next' is used before being assigned.

Note: replacing the variable assignment with inline returns (e.g. case Level.One: return Level.Two;) appears to negate the problem in this instance, but that isn't an option in the code that this example was derived from since there's additional code that uses the value of next.

@ahejlsberg
Copy link
Member

This would require the control flow analyzer to reason about dependencies between variables which is beyond its current capabilities. We're tracking a similar request in #12184. Effectively, definite assignment analysis is limited to conclusions based on the structure of the code.

@ahejlsberg ahejlsberg added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Sep 10, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Sep 25, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Sep 25, 2017
@calebsander
Copy link
Contributor

How does this require tracking dependencies between variables? It seems like the compiler should be able to reason that every code path assigns a value to next.

Here is an example of code that similarly fails to compile:

const A = 'A', B = 'B'
const makeChar = () => Math.random() > 0.5 ? A : B
const char = makeChar()
let response: string
if (char === A) response = '1'
else if (char === B) response = '2'
/*else char*/
console.log(response) //"Variable 'response' is being used before being assigned."

If you uncomment the else block and hover over char in it, you can see that it has type never, so the compiler is correctly inferring that that block is unreachable. In other situations where every code path assigns a value to a variable, the compiler does realize that the variable must have been assigned a value:

const A = 'A', B = 'B'
const makeChar = () => Math.random() > 0.5 ? A : B
const char = makeChar()
let response: string
if (char === A) response = '1'
else response = '2'
console.log(response) //no error

@RyanCavanaugh
Copy link
Member

@calebsander there's a distinction between inference that can be done syntactically (the second example) that that which requires type analysis (the first kind).

This is all in principle possible but we don't currently support inference that requires multiple passes that combine syntactic flow and type information. Generalizing your first example to the broadest case implies an analysis that has either an unbounded number of passes, or a completely different inference strategy.

@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
@jack-williams jack-williams added the Fixed A PR has been merged for this issue label Oct 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants