Home > Enterprise >  TypeScript complains about unassigned variable despite exhaustive if/if else statement
TypeScript complains about unassigned variable despite exhaustive if/if else statement

Time:01-12

Consider this code snippet:

type MyType = "value1" | "value2"

function myFunction(myParam: MyType) {
  let myString: string
  if(myParam === "value1") {
    myString = "foo1"
  }
  else if(myParam === "value2") {
    myString = "foo2"
  }
  myOtherFunction(myString) 
}

function myOtherFunction(anotherParam: string) { ... }

Since the if/if else handles all values of myParam, there is no way myString can be unassigned. Still, TypeScript complains: Variable 'myString' is used before being assigned.

How can I get rid of that error without substantial code changes?

(Of course, I could remove the if(myParam === "value2") part, but that makes the code much less readable. A switch works as well I think. But I dislike those.)

CodePudding user response:

The way to "fix" this is to throw in an additional else

type MyType = "value1" | "value2"

function myFunction(myParam: MyType) {
  let myString: string
  if(myParam === "value1") {
    myString = "foo1"
  }
  else if(myParam === "value2") {
    myString = "foo2"
  }
  else {
    // const unknownType = myParam; // You can use this line to check what type is myParam
    throw new Error('myParam is wrong!');
  }

  // ...
}

By throwing in the else you ensure typescript that the path that should not be taken really cannot be taken.


Also for this kind of thing, I tend to use switch for clarity, but it is viable only for primitives...

CodePudding user response:

The if .. else is exhaustive only when the last else does not have if:

type MyType = "value1" | "value2"

function myFunction(myParam: MyType) {
  let myString: string
  if(myParam === "value1") {
    myString = "foo1"
  }
  else { // <-- no "if" here
    myString = "foo2"
  }

  // `myString` is definitely assigned a value here

  myOtherFunction(myString)
}

function myOtherFunction(anotherParam: string) { ... }

CodePudding user response:

You could switch to switch (ugh.., sorry) and make the second case default:

type MyType = "value1" | "value2"

function myFunction(myParam: MyType) {
  let myString: string

  switch (myParam) {
    case "value1":
      myString = "foo1"
      break
    case "value2":
    default:
      myString = "foo2"
      break
  }

  myOtherFunction(myString)
}

function myOtherFunction(anotherParam: string) { ... }
  •  Tags:  
  • Related