最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

typescript complains even though it won't reach the statement - Stack Overflow

programmeradmin0浏览0评论

Why typescript still complains here even though we have satisfied all possible case values and it will never reach that default case?

I do this because incase I add new string literal to the Status type and I fet to handle the new cases in switch statement it will reach the default case which return a booleanwhich is not allowed because our doSomeAction's returntype is void so typescript will warn us.

type Status = "Pending" | "Working" | "Complete";

function doSomeAction(status: Status): void {
  switch (status) {
    case "Pending":
      // some code
      break;
    case "Working":
      // some code
      break;
    case "Complete":
      // some code
      break;
    default:
      return false  //<-- Type 'boolean' is not assignable to type 'void'.ts(2322)
  }
}

Edit:

I have a solution to this like this:

function doSomeAction(status: Status): void {
  switch (status) {
    ...
    ...
    default:
      neverReached(status) //typescript is happy here, no squiggly line
  }
}

function neverReached(never: never) {}

Here, typescript will only show squiggly line if we haven't handled added cases so this is what I wanted.

I just want an explanation on why typescript doesn't like the return version.

Why typescript still complains here even though we have satisfied all possible case values and it will never reach that default case?

I do this because incase I add new string literal to the Status type and I fet to handle the new cases in switch statement it will reach the default case which return a booleanwhich is not allowed because our doSomeAction's returntype is void so typescript will warn us.

type Status = "Pending" | "Working" | "Complete";

function doSomeAction(status: Status): void {
  switch (status) {
    case "Pending":
      // some code
      break;
    case "Working":
      // some code
      break;
    case "Complete":
      // some code
      break;
    default:
      return false  //<-- Type 'boolean' is not assignable to type 'void'.ts(2322)
  }
}

Edit:

I have a solution to this like this:

function doSomeAction(status: Status): void {
  switch (status) {
    ...
    ...
    default:
      neverReached(status) //typescript is happy here, no squiggly line
  }
}

function neverReached(never: never) {}

Here, typescript will only show squiggly line if we haven't handled added cases so this is what I wanted.

I just want an explanation on why typescript doesn't like the return version.

Share Improve this question edited Nov 19, 2024 at 19:41 kal_stackO asked Nov 19, 2024 at 15:53 kal_stackOkal_stackO 871 silver badge8 bronze badges 9
  • doSomeAction("wrong" as any) – knittl Commented Nov 19, 2024 at 15:57
  • I don't know why so I can't answer the question, but you can throw new Error(`Unexpected status "${status}" in doSomeAction`); instead of returning false. – Quentin Commented Nov 19, 2024 at 16:01
  • 5 TS doesn't use reachability to determine return type. There are issues like ms/TS#51800 and ms/TS#55437 where people don't like this but it's not clear anyone really wants to change it. On the face of it I'd say return false looks like a bug to me, even if it's unreachable. The standard TS approach is assertNever(), as shown here. It's based on types, not reachability. Does that fully address the q? If so I'll write an answer; if not, what's missing? – jcalz Commented Nov 19, 2024 at 16:27
  • 2 You return a boolean where your function return type is void. Of course it will complain. – Andrei Tătar Commented Nov 19, 2024 at 16:43
  • 1 @jcalz - sorry, I just read the short comment first and tried to understand them, I will surely read yours, and I'm also doing something – kal_stackO Commented Nov 19, 2024 at 19:48
 |  Show 4 more comments

1 Answer 1

Reset to default 1

Because it's still wrong. As @knittl noted, if someone does something unsound or if, as you mentioned, you add new cases, the case will be wrong. From a typing perspective, false is not assignable to void, void is nothing, and false is a boolean, not a subtype of nothing. You can't pass something to nothing. If you want to ensure you handle all possible cases, consider adding logging to catch it at runtime (or don't) or enabling typescript-eslint/switch-exhaustiveness-check to catch it at compiletime, or (as @Quentin noted) throw an error (though that might not leave the user in a nice state).

发布评论

评论列表(0)

  1. 暂无评论