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 boolean
which 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 boolean
which 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 | Show 4 more comments1 Answer
Reset to default 1Because 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).
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742416545a4439853.html
doSomeAction("wrong" as any)
– knittl Commented Nov 19, 2024 at 15:57throw new Error(`Unexpected status "${status}" in doSomeAction`);
instead of returning false. – Quentin Commented Nov 19, 2024 at 16:01return false
looks like a bug to me, even if it's unreachable. The standard TS approach isassertNever()
, 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:27boolean
where your function return type isvoid
. Of course it will complain. – Andrei Tătar Commented Nov 19, 2024 at 16:43